#!/usr/bin/env python3 """Smoke-test core prompt routes without importing ComfyUI. The checks here are intentionally lightweight invariants, not golden prompt snapshots. They prove that representative rows still carry structured metadata and that the Krea2, SDXL, and caption formatter paths consume metadata instead of silently falling back to raw text parsing. """ from __future__ import annotations import argparse import json import re import sys from dataclasses import dataclass, field from pathlib import Path from typing import Any, Callable ROOT = Path(__file__).resolve().parents[1] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) import caption_naturalizer # noqa: E402 import krea_formatter # noqa: E402 import prompt_builder as pb # noqa: E402 import sdxl_formatter # noqa: E402 Trigger = "sxcppnl7" SdxlTrigger = "mythp0rt" @dataclass class SmokeReport: passed: list[str] = field(default_factory=list) failed: list[str] = field(default_factory=list) def ok(self, name: str) -> None: self.passed.append(name) print(f"PASS {name}") def fail(self, name: str, message: str) -> None: detail = f"{name}: {message}" self.failed.append(detail) print(f"FAIL {detail}") def _clean_key(value: str) -> str: return re.sub(r"[^a-z0-9]+", " ", str(value or "").lower()).strip() def _json(value: Any) -> str: return json.dumps(value, ensure_ascii=True, sort_keys=True) def _expect(condition: bool, message: str) -> None: if not condition: raise AssertionError(message) def _expect_text(name: str, value: Any, min_len: int = 8) -> str: text = str(value or "").strip() _expect(len(text) >= min_len, f"{name} is empty or too short") _expect("None" not in text, f"{name} leaked None") _expect(" " not in text, f"{name} has repeated spaces") _expect(" ," not in text and " ." not in text, f"{name} has bad punctuation spacing") return text def _expect_no_duplicate_comma_items(name: str, value: Any) -> None: items = [_clean_key(part) for part in str(value or "").split(",")] items = [part for part in items if part] duplicates = sorted({part for part in items if items.count(part) > 1}) _expect(not duplicates, f"{name} has duplicate comma items: {duplicates[:5]}") def _trigger_count(text: str, trigger: str) -> int: return len(re.findall(rf"(? None: text = str(value or "") count = _trigger_count(text, trigger) _expect(count == 1, f"{name} should contain trigger {trigger!r} exactly once, got {count}") def _expect_row_base(row: dict[str, Any], name: str) -> None: _expect(isinstance(row, dict), f"{name} did not return a metadata row") _expect_text(f"{name}.prompt", row.get("prompt"), 20) _expect_text(f"{name}.negative_prompt", row.get("negative_prompt"), 8) _expect_no_duplicate_comma_items(f"{name}.negative_prompt", row.get("negative_prompt")) _expect(json.loads(_json(row)) == row, f"{name} is not JSON-stable") def _expect_custom_row(row: dict[str, Any], name: str) -> None: _expect_row_base(row, name) _expect(row.get("source") == "json_category", f"{name}.source should be json_category") _expect_text(f"{name}.item", row.get("item"), 8) _expect_text(f"{name}.scene_text", row.get("scene_text"), 8) _expect_text(f"{name}.composition", row.get("composition"), 8) _expect_text(f"{name}.role_graph", row.get("source_role_graph") or row.get("role_graph"), 8) _expect(isinstance(row.get("item_axis_values"), dict), f"{name}.item_axis_values missing") def _expect_formatter_outputs(row: dict[str, Any], name: str, *, target: str = "auto") -> None: metadata = _json(row) krea = krea_formatter.format_krea2_prompt("", metadata_json=metadata, target=target) _expect("metadata" in krea.get("method", ""), f"{name}.krea did not use metadata: {krea.get('method')}") _expect_text(f"{name}.krea_prompt", krea.get("krea_prompt"), 20) _expect_no_duplicate_comma_items(f"{name}.krea_negative", krea.get("negative_prompt")) sdxl = sdxl_formatter.format_sdxl_prompt( "", metadata_json=metadata, target=target, trigger=SdxlTrigger, prepend_trigger=True, ) _expect("metadata" in sdxl.get("method", ""), f"{name}.sdxl did not use metadata: {sdxl.get('method')}") _expect_text(f"{name}.sdxl_prompt", sdxl.get("sdxl_prompt"), 20) _expect_trigger_once(f"{name}.sdxl_prompt", sdxl.get("sdxl_prompt"), SdxlTrigger) _expect_no_duplicate_comma_items(f"{name}.sdxl_negative", sdxl.get("negative_prompt")) caption, method = caption_naturalizer.naturalize_caption( "", metadata_json=metadata, trigger=Trigger, include_trigger=True, ) _expect("metadata" in method, f"{name}.caption did not use metadata: {method}") _expect_text(f"{name}.caption", caption, 20) _expect_trigger_once(f"{name}.caption", caption, Trigger) def _character_cast(*, pov_man: bool = False) -> str: cast = pb.build_character_slot_json( subject_type="woman", label="A", age="25-year-old adult", ethnicity="western_european", figure="balanced", body="slim", descriptor_detail="full", expression_intensity=0.65, softcore_expression_intensity=0.45, hardcore_expression_intensity=0.85, )["character_cast"] return pb.build_character_slot_json( subject_type="man", label="A", age="40-year-old adult", ethnicity="western_european", figure="balanced", body="average", descriptor_detail="compact", expression_intensity=0.55, softcore_expression_intensity=0.35, hardcore_expression_intensity=0.75, presence_mode="pov" if pov_man else "visible", character_cast=cast, )["character_cast"] def _action_filter(focus: str) -> str: kwargs = { "allow_toys": False, "allow_double": False, "allow_penetration": focus in ("penetration_only", "keep_pool"), "allow_foreplay": focus in ("foreplay_only", "keep_pool"), "allow_interaction": focus in ("interaction_only", "keep_pool"), "allow_manual": focus in ("manual_only", "keep_pool"), "allow_oral": focus in ("oral_only", "keep_pool"), "allow_outercourse": focus in ("outercourse_only", "keep_pool"), "allow_anal": focus in ("anal_only", "keep_pool"), "allow_climax": focus in ("climax_only", "keep_pool"), } return pb.build_hardcore_action_filter_json(focus=focus, **kwargs) def _coworking_location_config() -> str: return pb.build_location_pool_json( enabled=True, combine_mode="replace", preset="custom_only", custom_locations=( "coworking_smoke: coworking lounge with tall windows, warm desks, " "laptop tables, glass partition seams, repeated desk rows, plants, " "and soft shared-office depth" ), ) def _classical_library_theme_configs() -> tuple[str, str]: location_config, composition_config, _summary = pb.build_thematic_location_json( enabled=True, combine_mode="replace", theme="classical_library", ) return location_config, composition_config def _orbit_camera( *, horizontal_angle: int, vertical_angle: int, zoom: float, subject_focus: str = "auto", camera_detail: str = "compact", ) -> str: return pb.build_camera_orbit_config_json( enabled=True, camera_mode="standard", horizontal_angle=horizontal_angle, vertical_angle=vertical_angle, zoom=zoom, framing="from_zoom", subject_focus=subject_focus, lens="auto", orientation="auto", phone_visibility="auto", priority="strong", camera_detail=camera_detail, include_degrees=True, ) def _prompt_row( *, name: str, category: str, subcategory: str, seed: int, character_cast: str = "", women_count: int = 1, men_count: int = 1, hardcore_position_config: str = "", camera_config: str | dict[str, Any] | None = "", location_config: str | dict[str, Any] | None = "", composition_config: str | dict[str, Any] | None = "", ) -> dict[str, Any]: row = pb.build_prompt( category=category, subcategory=subcategory, row_number=1, start_index=1, seed=seed, clothing="random", ethnicity="any", poses="random", backside_bias=0.35, figure="random", no_plus_women=False, no_black=False, minimal_clothing_ratio=0.5, standard_pose_ratio=0.5, trigger=Trigger, prepend_trigger_to_prompt=True, extra_positive="", extra_negative="", character_cast=character_cast, women_count=women_count, men_count=men_count, expression_enabled=True, expression_intensity=0.6, hardcore_position_config=hardcore_position_config, camera_config=camera_config, location_config=location_config, composition_config=composition_config, ) _expect_row_base(row, name) return row def smoke_builtin_single() -> None: row = _prompt_row(name="builtin_single_woman", category="woman", subcategory="random", seed=1001, men_count=0) _expect(row.get("source") == "built_in_generator", "builtin row should come from built-in generator") _expect_trigger_once("builtin_single_woman.prompt", row.get("prompt"), Trigger) _expect_formatter_outputs(row, "builtin_single_woman", target="single") def smoke_camera_scene_single() -> None: row = _prompt_row( name="camera_scene_single", category="woman", subcategory="random", seed=1051, men_count=0, camera_config=_orbit_camera( horizontal_angle=45, vertical_angle=-30, zoom=5.0, subject_focus="environment", ), location_config=_coworking_location_config(), ) scene_directive = _expect_text("camera_scene_single.camera_scene_directive", row.get("camera_scene_directive"), 40) camera_directive = _expect_text("camera_scene_single.camera_directive", row.get("camera_directive"), 20) _expect("Coworking camera layout" in scene_directive, "single camera-scene adapter did not identify coworking layout") _expect("front-right quarter view" in scene_directive, "single camera scene missed orbit direction") _expect("low-angle shot" in scene_directive, "single camera scene missed orbit elevation") _expect("45-degree front-right quarter view" in camera_directive, "single camera directive missed custom orbit prompt") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single") prompt = krea.get("krea_prompt") or "" _expect("Coworking camera layout" in prompt, "Krea single prompt lost camera-scene directive") _expect("45-degree front-right quarter view" in prompt, "Krea single prompt lost camera directive") _expect_formatter_outputs(row, "camera_scene_single", target="single") def smoke_config_route_location_theme() -> None: location_config, composition_config = _classical_library_theme_configs() row = pb.build_prompt_from_configs( row_number=1, start_index=1, seed=3301, category_config=pb.build_category_config_json("hardcore_pose", "Foreplay and teasing"), cast_config=pb.build_cast_config_json("mixed_couple"), generation_profile=pb.build_generation_profile_json( profile="hardcore_intense", trigger_policy="prepend_trigger", ), filter_config=pb.build_ethnicity_list_json( include_french_european=True, strict_excludes=True, )["filter_config"], seed_config=pb.build_seed_lock_config_json( base_seed=3301, reroll_axis="pose", reroll_seed=3302, ), camera_config=_orbit_camera( horizontal_angle=315, vertical_angle=0, zoom=5.0, subject_focus="action", ), character_cast=_character_cast(), hardcore_position_config=_action_filter("foreplay_only"), location_config=location_config, composition_config=composition_config, ) _expect_custom_row(row, "config_route_location_theme") _expect(row.get("subcategory") == "Foreplay and teasing", "config route did not preserve requested subcategory") _expect(row.get("subject_type") == "configured_cast", "config route did not apply character cast") scene = _expect_text("config_route_location_theme.scene_text", row.get("scene_text"), 20) composition = _expect_text("config_route_location_theme.composition", row.get("composition"), 10) camera = _expect_text("config_route_location_theme.camera_directive", row.get("camera_directive"), 20) _expect("library" in scene.lower() or "bookshelves" in scene.lower(), "location theme did not drive scene") _expect("books" in composition.lower() or "shelf" in composition.lower() or "library" in composition.lower(), "location theme did not drive composition") _expect("315-degree front-left quarter view" in camera, "config route did not preserve orbit camera directive") seed_config = row.get("seed_config") if isinstance(row.get("seed_config"), dict) else {} _expect(seed_config.get("pose_seed") == 3302, "seed lock did not reroll pose axis") _expect(seed_config.get("role_seed") == 3302, "seed lock did not reroll role axis") _expect(row.get("trigger") == "sxcpinup_coloredpencil", "generation profile trigger did not apply") _expect_trigger_once("config_route_location_theme.prompt", row.get("prompt"), "sxcpinup_coloredpencil") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single") prompt = krea.get("krea_prompt") or "" _expect("library" in prompt.lower() or "bookshelves" in prompt.lower(), "Krea config route lost theme scene") _expect("315-degree front-left quarter view" in prompt, "Krea config route lost camera directive") _expect_formatter_outputs(row, "config_route_location_theme", target="single") def smoke_hardcore_category_routes() -> None: cast = _character_cast() cases = [ ("hardcore_penetration", "Penetrative sex", "penetration_only"), ("hardcore_oral", "Oral sex", "oral_only"), ("hardcore_manual", "Manual stimulation", "manual_only"), ("hardcore_outercourse", "Outercourse and genital teasing", "outercourse_only"), ("hardcore_foreplay", "Foreplay and teasing", "foreplay_only"), ("hardcore_aftercare", "Aftercare and cleanup", "interaction_only"), ] for index, (name, subcategory, focus) in enumerate(cases, start=1101): row = _prompt_row( name=name, category="Hardcore sexual poses", subcategory=subcategory, seed=index, character_cast=cast, women_count=1, men_count=1, hardcore_position_config=_action_filter(focus), ) _expect_custom_row(row, name) _expect(row.get("subject_type") == "configured_cast", f"{name} should use configured cast") _expect_formatter_outputs(row, name, target="single") def smoke_krea_close_foreplay_route() -> None: row = _prompt_row( name="krea_close_foreplay_route", category="Hardcore sexual poses", subcategory="Foreplay and teasing", seed=3401, character_cast=_character_cast(), women_count=1, men_count=1, hardcore_position_config=_action_filter("foreplay_only"), ) _expect_custom_row(row, "krea_close_foreplay_route") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single") prompt = _expect_text("krea_close_foreplay_route.krea_prompt", krea.get("krea_prompt"), 40) lower = prompt.lower() _expect("metadata" in krea.get("method", ""), "close foreplay route did not use metadata") _expect("role graph:" not in lower, "close foreplay leaked raw role label") _expect("foreplay action:" not in lower, "close foreplay leaked raw item label") _expect("on against" not in lower, "close foreplay kept invalid surface grammar") _expect( any(term in lower for term in ("clothing", "hands", "kiss", "bodies press", "body contact")), "close foreplay lost close-contact action wording", ) _expect_formatter_outputs(row, "krea_close_foreplay_route", target="single") def _insta_options(**overrides: Any) -> str: options = pb.build_insta_of_options_json( softcore_cast="same_as_hardcore", hardcore_cast="couple", hardcore_women_count=1, hardcore_men_count=1, softcore_level="lingerie_tease", hardcore_level="hardcore", platform_style="hybrid", continuity="same_creator_same_room", hardcore_clothing_continuity="explicit_nude", softcore_camera_mode="standard", hardcore_camera_mode="standard", camera_detail="compact", hardcore_detail_density="balanced", ) data = json.loads(options) data.update(overrides) return _json(data) def _expect_pair(pair: dict[str, Any], name: str) -> None: _expect(pair.get("mode") == "Insta/OF", f"{name}.mode should be Insta/OF") _expect_row_base(pair.get("softcore_row") or {}, f"{name}.softcore_row") _expect_custom_row(pair.get("hardcore_row") or {}, f"{name}.hardcore_row") _expect_text(f"{name}.softcore_prompt", pair.get("softcore_prompt"), 20) _expect_text(f"{name}.hardcore_prompt", pair.get("hardcore_prompt"), 20) _expect_no_duplicate_comma_items(f"{name}.softcore_negative", pair.get("softcore_negative_prompt")) _expect_no_duplicate_comma_items(f"{name}.hardcore_negative", pair.get("hardcore_negative_prompt")) _expect_formatter_outputs(pair, name, target="softcore") _expect_formatter_outputs(pair, f"{name}.hardcore", target="hardcore") def smoke_insta_pair() -> None: pair = pb.build_insta_of_pair( row_number=1, start_index=1, seed=2101, ethnicity="any", figure="random", no_plus_women=False, no_black=False, trigger=Trigger, prepend_trigger_to_prompt=True, options_json=_insta_options(), character_cast=_character_cast(), hardcore_position_config=_action_filter("penetration_only"), ) _expect_pair(pair, "insta_pair_same_cast") _expect(pair["softcore_row"].get("scene_text") == pair["hardcore_row"].get("scene_text"), "pair scene continuity broke") clothing_state = _clean_key(pair.get("hardcore_clothing_state")) _expect("body is fully exposed" in clothing_state, "explicit nude pair should keep body exposure state") _expect("teaser outfit detail" not in clothing_state, "explicit nude pair should not repeat softcore outfit detail") def smoke_krea_pair_clothing_state() -> None: pair = pb.build_insta_of_pair( row_number=1, start_index=1, seed=3511, ethnicity="any", figure="random", no_plus_women=False, no_black=False, trigger=Trigger, prepend_trigger_to_prompt=True, options_json=_insta_options(hardcore_clothing_continuity="partially_removed"), character_cast=_character_cast(), hardcore_position_config=_action_filter("penetration_only"), ) _expect_pair(pair, "krea_pair_clothing_state") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore") prompt = _expect_text("krea_pair_clothing_state.krea_prompt", krea.get("krea_prompt"), 60) lower = prompt.lower() _expect("metadata" in krea.get("method", ""), "pair clothing route did not use metadata") _expect("clothing state:" not in lower, "Krea clothing route leaked raw clothing label") _expect("visual clothing state" not in lower, "Krea clothing route fell back to visual clothing state label") _expect("softcore outfit" not in lower and "teaser outfit" not in lower, "Krea clothing route leaked softcore outfit label") _expect("lower body is clear" in lower, "Krea clothing route lost generated clothing continuity") _expect("the man keeps" in lower, "Krea clothing route lost partner clothing continuity") def smoke_insta_pair_pov() -> None: pair = pb.build_insta_of_pair( row_number=1, start_index=1, seed=2201, ethnicity="any", figure="random", no_plus_women=False, no_black=False, trigger=Trigger, prepend_trigger_to_prompt=True, options_json=_insta_options(), character_cast=_character_cast(pov_man=True), hardcore_position_config=_action_filter("oral_only"), ) _expect_pair(pair, "insta_pair_pov_man") pov_labels = pair.get("pov_character_labels") or [] _expect("Man A" in pov_labels, "pair POV labels should include Man A") hard_row = pair.get("hardcore_row") or {} _expect("Man A" in (hard_row.get("pov_character_labels") or []), "hard row POV labels should include Man A") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore") prompt = krea.get("krea_prompt") or "" _expect("viewer" in prompt.lower(), "POV Krea prompt should mention viewer perspective") def smoke_insta_pair_camera_split() -> None: soft_camera = _orbit_camera( horizontal_angle=45, vertical_angle=-30, zoom=5.0, subject_focus="environment", ) hard_camera = _orbit_camera( horizontal_angle=135, vertical_angle=30, zoom=8.0, subject_focus="action", ) pair = pb.build_insta_of_pair( row_number=1, start_index=1, seed=2251, ethnicity="any", figure="random", no_plus_women=False, no_black=False, trigger=Trigger, prepend_trigger_to_prompt=True, options_json=_insta_options( softcore_camera_mode="from_camera_config", hardcore_camera_mode="from_camera_config", camera_detail="compact", ), character_cast=_character_cast(), hardcore_position_config=_action_filter("penetration_only"), location_config=_coworking_location_config(), softcore_camera_config=soft_camera, hardcore_camera_config=hard_camera, ) _expect_pair(pair, "insta_pair_camera_split") soft_scene = _expect_text("insta_pair_camera_split.soft_camera_scene", pair.get("softcore_camera_scene_directive"), 40) hard_scene = _expect_text("insta_pair_camera_split.hard_camera_scene", pair.get("hardcore_camera_scene_directive"), 40) _expect("front-right quarter view" in soft_scene, "soft camera scene missed soft orbit direction") _expect("back-right quarter view" in hard_scene, "hard camera scene missed hard orbit direction") _expect("low-angle shot" in soft_scene, "soft camera scene missed soft elevation") _expect("elevated shot" in hard_scene, "hard camera scene missed hard elevation") _expect("front-right quarter view" in str(pair.get("softcore_camera_directive")), "soft pair camera directive was not preserved") _expect("back-right quarter view" in str(pair.get("hardcore_camera_directive")), "hard pair camera directive was not preserved") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="auto") _expect("front-right quarter view" in (krea.get("krea_softcore_prompt") or ""), "Krea soft pair lost soft camera geometry") _expect("back-right quarter view" in (krea.get("krea_hardcore_prompt") or ""), "Krea hard pair lost hard camera geometry") def smoke_pov_camera_scene() -> None: pair = pb.build_insta_of_pair( row_number=1, start_index=1, seed=2261, ethnicity="any", figure="random", no_plus_women=False, no_black=False, trigger=Trigger, prepend_trigger_to_prompt=True, options_json=_insta_options( softcore_camera_mode="from_camera_config", hardcore_camera_mode="from_camera_config", camera_detail="compact", ), character_cast=_character_cast(pov_man=True), hardcore_position_config=_action_filter("oral_only"), location_config=_coworking_location_config(), hardcore_camera_config=_orbit_camera( horizontal_angle=135, vertical_angle=30, zoom=8.0, subject_focus="action", ), ) _expect_pair(pair, "pov_camera_scene") hard_row = pair.get("hardcore_row") or {} _expect(not hard_row.get("camera_directive"), "POV hard row should suppress normal camera directive") scene_directive = _expect_text("pov_camera_scene.hard_camera_scene", hard_row.get("camera_scene_directive"), 40) _expect("from POV" in scene_directive, "POV camera scene should be marked as first-person") _expect("not in the lower foreground" in scene_directive, "POV camera scene should keep location anchors out of lower foreground") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore") prompt = krea.get("krea_prompt") or "" _expect("from POV" in prompt, "Krea POV prompt lost camera-scene directive") _expect("Camera:" not in prompt, "Krea POV prompt should not emit normal third-person camera directive") def smoke_krea_pov_penetration_route() -> None: pair = pb.build_insta_of_pair( row_number=1, start_index=1, seed=3411, ethnicity="any", figure="random", no_plus_women=False, no_black=False, trigger=Trigger, prepend_trigger_to_prompt=True, options_json=_insta_options( softcore_camera_mode="from_camera_config", hardcore_camera_mode="from_camera_config", camera_detail="compact", ), character_cast=_character_cast(pov_man=True), hardcore_position_config=_action_filter("penetration_only"), location_config=_coworking_location_config(), hardcore_camera_config=_orbit_camera( horizontal_angle=45, vertical_angle=0, zoom=5.5, subject_focus="action", ), ) _expect_pair(pair, "krea_pov_penetration_route") hard_row = pair.get("hardcore_row") or {} _expect("Man A" in (hard_row.get("pov_character_labels") or []), "POV penetration hard row lost Man A POV label") _expect(not hard_row.get("camera_directive"), "POV penetration should suppress normal camera directive") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore") prompt = _expect_text("krea_pov_penetration_route.krea_prompt", krea.get("krea_prompt"), 60) lower = prompt.lower() _expect("metadata" in krea.get("method", ""), "POV penetration route did not use metadata") _expect("viewer" in lower and "first-person" in lower, "POV penetration lost first-person wording") _expect("penetrates" in lower or "penetration" in lower, "POV penetration lost penetration action wording") _expect("woman" in lower and "thigh" in lower, "POV penetration lost body-position anchors") _expect("camera:" not in prompt, "POV penetration emitted normal third-person camera directive") _expect("role graph:" not in lower and "sexual scene:" not in lower, "POV penetration leaked raw prompt labels") _expect("composition. explicit" in lower, "POV penetration composition sentence should keep punctuation before style suffix") def smoke_no_expression_fallback() -> None: cast = pb.build_character_slot_json( subject_type="woman", label="A", age="25-year-old adult", ethnicity="western_european", body="slim", descriptor_detail="full", expression_enabled=False, )["character_cast"] row = _prompt_row( name="hardcore_expression_disabled", category="Hardcore sexual poses", subcategory="Penetrative sex", seed=2301, character_cast=cast, women_count=1, men_count=1, hardcore_position_config=_action_filter("penetration_only"), ) _expect_custom_row(row, "hardcore_expression_disabled") _expect(not row.get("expression"), "expression should stay disabled without fallback") _expect("Facial expressions:" not in row.get("prompt", ""), "disabled expression leaked into prompt") _expect_formatter_outputs(row, "hardcore_expression_disabled", target="single") SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [ ("builtin_single_woman", smoke_builtin_single), ("camera_scene_single", smoke_camera_scene_single), ("config_route_location_theme", smoke_config_route_location_theme), ("hardcore_category_routes", smoke_hardcore_category_routes), ("krea_close_foreplay_route", smoke_krea_close_foreplay_route), ("insta_pair_same_cast", smoke_insta_pair), ("krea_pair_clothing_state", smoke_krea_pair_clothing_state), ("insta_pair_pov_man", smoke_insta_pair_pov), ("insta_pair_camera_split", smoke_insta_pair_camera_split), ("pov_camera_scene", smoke_pov_camera_scene), ("krea_pov_penetration_route", smoke_krea_pov_penetration_route), ("expression_disabled", smoke_no_expression_fallback), ] def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--case", choices=[name for name, _func in SMOKE_CASES], action="append", help="Run only the named smoke case. Can be passed multiple times.", ) args = parser.parse_args(argv) selected = set(args.case or []) report = SmokeReport() for name, func in SMOKE_CASES: if selected and name not in selected: continue try: func() except Exception as exc: # noqa: BLE001 - report all smoke failures uniformly. report.fail(name, str(exc)) else: report.ok(name) print(f"\nSummary: {len(report.passed)} passed, {len(report.failed)} failed") if report.failed: return 1 return 0 if __name__ == "__main__": raise SystemExit(main())