Tighten Krea2 POV selector formatting
This commit is contained in:
@@ -4,6 +4,10 @@ from dataclasses import dataclass
|
|||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
|
MOUTH_EXPRESSION_TERMS = ("mouth", "oral", "tongue", "lips", "gagging", "saliva", "drool")
|
||||||
|
TOP_VIEW_ORAL_VARIANT = "pov_blowjob_top_down_vertical_shaft"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class KreaConfiguredCastRequest:
|
class KreaConfiguredCastRequest:
|
||||||
row: dict[str, Any]
|
row: dict[str, Any]
|
||||||
@@ -76,6 +80,45 @@ def _coworking_action_anchor(action_family: str, scene_text: str, action: str) -
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _list_values(value: Any) -> list[str]:
|
||||||
|
if isinstance(value, list):
|
||||||
|
return [str(item) for item in value if str(item).strip()]
|
||||||
|
if isinstance(value, str) and value.strip():
|
||||||
|
return [part.strip() for part in value.split(",") if part.strip()]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def _krea2_variant_keys(row: dict[str, Any]) -> list[str]:
|
||||||
|
config = row.get("hardcore_position_config") if isinstance(row.get("hardcore_position_config"), dict) else {}
|
||||||
|
axis_values = row.get("item_axis_values") if isinstance(row.get("item_axis_values"), dict) else {}
|
||||||
|
return list(dict.fromkeys([*_list_values(config.get("krea2_variant_keys")), *_list_values(axis_values.get("krea2_variant_keys"))]))
|
||||||
|
|
||||||
|
|
||||||
|
def _has_krea2_variant(row: dict[str, Any], key: str) -> bool:
|
||||||
|
return key in _krea2_variant_keys(row)
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_expression_for_krea2_variant(row: dict[str, Any], expression: Any) -> Any:
|
||||||
|
if not _has_krea2_variant(row, TOP_VIEW_ORAL_VARIANT):
|
||||||
|
return expression
|
||||||
|
clauses = [clause.strip() for clause in str(expression or "").split(";") if clause.strip()]
|
||||||
|
if not clauses:
|
||||||
|
return expression
|
||||||
|
kept = [
|
||||||
|
clause
|
||||||
|
for clause in clauses
|
||||||
|
if not any(term in clause.lower() for term in MOUTH_EXPRESSION_TERMS)
|
||||||
|
]
|
||||||
|
return "; ".join(kept)
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_camera_scene_for_krea2_variant(row: dict[str, Any], camera_scene: Any) -> str:
|
||||||
|
text = str(camera_scene or "")
|
||||||
|
if _has_krea2_variant(row, TOP_VIEW_ORAL_VARIANT) and "eye-level" in text.lower():
|
||||||
|
return ""
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
def format_configured_cast_result(
|
def format_configured_cast_result(
|
||||||
request: KreaConfiguredCastRequest,
|
request: KreaConfiguredCastRequest,
|
||||||
deps: KreaConfiguredCastDependencies,
|
deps: KreaConfiguredCastDependencies,
|
||||||
@@ -97,7 +140,8 @@ def format_configured_cast_result(
|
|||||||
if not cast_labels and women_count == 1 and men_count == 1:
|
if not cast_labels and women_count == 1 and men_count == 1:
|
||||||
cast_labels = ["Woman A", "Man A"]
|
cast_labels = ["Woman A", "Man A"]
|
||||||
cast_labels = deps.merge_labels(cast_labels, pov_labels)
|
cast_labels = deps.merge_labels(cast_labels, pov_labels)
|
||||||
expression = deps.filter_pov_labeled_clauses(request.expression, pov_labels)
|
expression = _filter_expression_for_krea2_variant(row, request.expression)
|
||||||
|
expression = deps.filter_pov_labeled_clauses(expression, pov_labels)
|
||||||
expression = deps.natural_label_text(expression, cast_labels)
|
expression = deps.natural_label_text(expression, cast_labels)
|
||||||
composition = deps.sanitize_hardcore_environment_anchors(request.composition)
|
composition = deps.sanitize_hardcore_environment_anchors(request.composition)
|
||||||
source_composition = deps.sanitize_hardcore_environment_anchors(request.source_composition)
|
source_composition = deps.sanitize_hardcore_environment_anchors(request.source_composition)
|
||||||
@@ -136,6 +180,7 @@ def format_configured_cast_result(
|
|||||||
" ".join(part for part in (request.scene, request.camera_scene, composition, source_composition) if part),
|
" ".join(part for part in (request.scene, request.camera_scene, composition, source_composition) if part),
|
||||||
action,
|
action,
|
||||||
)
|
)
|
||||||
|
camera_scene = _filter_camera_scene_for_krea2_variant(row, request.camera_scene)
|
||||||
output_composition = deps.pov_composition_text(composition, pov_labels)
|
output_composition = deps.pov_composition_text(composition, pov_labels)
|
||||||
parts = [
|
parts = [
|
||||||
action,
|
action,
|
||||||
@@ -145,7 +190,7 @@ def format_configured_cast_result(
|
|||||||
f"A consensual explicit adult scene with {subject}" if not action else "",
|
f"A consensual explicit adult scene with {subject}" if not action else "",
|
||||||
f"The cast includes {cast}" if cast and not cast_prose and not (women_count == 1 and men_count == 1) else "",
|
f"The cast includes {cast}" if cast and not cast_prose and not (women_count == 1 and men_count == 1) else "",
|
||||||
f"The setting is {request.scene}" if request.scene else "",
|
f"The setting is {request.scene}" if request.scene else "",
|
||||||
request.camera_scene,
|
camera_scene,
|
||||||
deps.expression_phrase(expression),
|
deps.expression_phrase(expression),
|
||||||
deps.composition_phrase(output_composition, action, "The image is framed as", detail_density),
|
deps.composition_phrase(output_composition, action, "The image is framed as", detail_density),
|
||||||
camera,
|
camera,
|
||||||
|
|||||||
+52
-2
@@ -4,6 +4,10 @@ from dataclasses import dataclass
|
|||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
|
MOUTH_EXPRESSION_TERMS = ("mouth", "oral", "tongue", "lips", "gagging", "saliva", "drool")
|
||||||
|
TOP_VIEW_ORAL_VARIANT = "pov_blowjob_top_down_vertical_shaft"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class KreaPairFormatRequest:
|
class KreaPairFormatRequest:
|
||||||
row: dict[str, Any]
|
row: dict[str, Any]
|
||||||
@@ -54,6 +58,45 @@ class KreaPairFormatDependencies:
|
|||||||
combine_negative: Callable[..., str]
|
combine_negative: Callable[..., str]
|
||||||
|
|
||||||
|
|
||||||
|
def _list_values(value: Any) -> list[str]:
|
||||||
|
if isinstance(value, list):
|
||||||
|
return [str(item) for item in value if str(item).strip()]
|
||||||
|
if isinstance(value, str) and value.strip():
|
||||||
|
return [part.strip() for part in value.split(",") if part.strip()]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def _krea2_variant_keys(row: dict[str, Any]) -> list[str]:
|
||||||
|
config = row.get("hardcore_position_config") if isinstance(row.get("hardcore_position_config"), dict) else {}
|
||||||
|
axis_values = row.get("item_axis_values") if isinstance(row.get("item_axis_values"), dict) else {}
|
||||||
|
return list(dict.fromkeys([*_list_values(config.get("krea2_variant_keys")), *_list_values(axis_values.get("krea2_variant_keys"))]))
|
||||||
|
|
||||||
|
|
||||||
|
def _has_krea2_variant(row: dict[str, Any], key: str) -> bool:
|
||||||
|
return key in _krea2_variant_keys(row)
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_expression_for_krea2_variant(row: dict[str, Any], expression: Any) -> Any:
|
||||||
|
if not _has_krea2_variant(row, TOP_VIEW_ORAL_VARIANT):
|
||||||
|
return expression
|
||||||
|
clauses = [clause.strip() for clause in str(expression or "").split(";") if clause.strip()]
|
||||||
|
if not clauses:
|
||||||
|
return expression
|
||||||
|
kept = [
|
||||||
|
clause
|
||||||
|
for clause in clauses
|
||||||
|
if not any(term in clause.lower() for term in MOUTH_EXPRESSION_TERMS)
|
||||||
|
]
|
||||||
|
return "; ".join(kept)
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_camera_scene_for_krea2_variant(row: dict[str, Any], camera_scene: Any) -> str:
|
||||||
|
text = str(camera_scene or "")
|
||||||
|
if _has_krea2_variant(row, TOP_VIEW_ORAL_VARIANT) and "eye-level" in text.lower():
|
||||||
|
return ""
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairFormatDependencies) -> KreaPairPrompts:
|
def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairFormatDependencies) -> KreaPairPrompts:
|
||||||
row = request.row
|
row = request.row
|
||||||
detail_level = request.detail_level
|
detail_level = request.detail_level
|
||||||
@@ -70,7 +113,10 @@ def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairForma
|
|||||||
soft_camera = deps.pair_camera_phrase(row.get("softcore_camera_directive"), row.get("softcore_camera_config"), soft)
|
soft_camera = deps.pair_camera_phrase(row.get("softcore_camera_directive"), row.get("softcore_camera_config"), soft)
|
||||||
hard_camera = deps.pair_camera_phrase(row.get("hardcore_camera_directive"), row.get("hardcore_camera_config"), hard)
|
hard_camera = deps.pair_camera_phrase(row.get("hardcore_camera_directive"), row.get("hardcore_camera_config"), hard)
|
||||||
soft_camera_scene = deps.camera_scene_phrase(soft) or deps.clean(row.get("softcore_camera_scene_directive"))
|
soft_camera_scene = deps.camera_scene_phrase(soft) or deps.clean(row.get("softcore_camera_scene_directive"))
|
||||||
hard_camera_scene = deps.camera_scene_phrase(hard) or deps.clean(row.get("hardcore_camera_scene_directive"))
|
hard_camera_scene = _filter_camera_scene_for_krea2_variant(
|
||||||
|
hard,
|
||||||
|
deps.camera_scene_phrase(hard) or deps.clean(row.get("hardcore_camera_scene_directive")),
|
||||||
|
)
|
||||||
soft_style = deps.style_phrase(soft, style_mode)
|
soft_style = deps.style_phrase(soft, style_mode)
|
||||||
hard_style = deps.style_phrase(hard, style_mode)
|
hard_style = deps.style_phrase(hard, style_mode)
|
||||||
options = row.get("options") if isinstance(row.get("options"), dict) else {}
|
options = row.get("options") if isinstance(row.get("options"), dict) else {}
|
||||||
@@ -166,8 +212,12 @@ def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairForma
|
|||||||
)
|
)
|
||||||
hard_expression = ""
|
hard_expression = ""
|
||||||
if not deps.expression_disabled(hard):
|
if not deps.expression_disabled(hard):
|
||||||
hard_expression_source = deps.filter_pov_labeled_clauses(
|
hard_expression_source = _filter_expression_for_krea2_variant(
|
||||||
|
hard,
|
||||||
deps.clean(hard.get("character_expression_text")) or deps.clean(hard.get("expression")),
|
deps.clean(hard.get("character_expression_text")) or deps.clean(hard.get("expression")),
|
||||||
|
)
|
||||||
|
hard_expression_source = deps.filter_pov_labeled_clauses(
|
||||||
|
hard_expression_source,
|
||||||
pov_labels,
|
pov_labels,
|
||||||
)
|
)
|
||||||
hard_expression = deps.natural_label_text(
|
hard_expression = deps.natural_label_text(
|
||||||
|
|||||||
+10
-14
@@ -131,17 +131,6 @@ def _merge_variant_metadata(config_json, variants):
|
|||||||
existing_statuses = config.get("krea2_variant_statuses") if isinstance(config.get("krea2_variant_statuses"), dict) else {}
|
existing_statuses = config.get("krea2_variant_statuses") if isinstance(config.get("krea2_variant_statuses"), dict) else {}
|
||||||
config["krea2_variant_statuses"] = {**existing_statuses, **selected_statuses}
|
config["krea2_variant_statuses"] = {**existing_statuses, **selected_statuses}
|
||||||
|
|
||||||
prompt_cues = _unique_extend(
|
|
||||||
[*(config.get("krea2_prompt_cues") or []), *(_join_variant_cues(variants, "prompt_cues").split("; ") if variants else [])]
|
|
||||||
)
|
|
||||||
avoid_cues = _unique_extend(
|
|
||||||
[*(config.get("krea2_avoid_cues") or []), *(_join_variant_cues(variants, "avoid_cues").split("; ") if variants else [])]
|
|
||||||
)
|
|
||||||
if prompt_cues:
|
|
||||||
config["krea2_prompt_cues"] = prompt_cues
|
|
||||||
if avoid_cues:
|
|
||||||
config["krea2_avoid_cues"] = avoid_cues
|
|
||||||
|
|
||||||
base_summary = str(config.get("summary") or hardcore_position_summary(config))
|
base_summary = str(config.get("summary") or hardcore_position_summary(config))
|
||||||
if variant_keys and "variants=" not in base_summary:
|
if variant_keys and "variants=" not in base_summary:
|
||||||
base_summary = f"{base_summary}; variants={','.join(variant_keys)}"
|
base_summary = f"{base_summary}; variants={','.join(variant_keys)}"
|
||||||
@@ -149,6 +138,14 @@ def _merge_variant_metadata(config_json, variants):
|
|||||||
return json.dumps(config, ensure_ascii=True, sort_keys=True)
|
return json.dumps(config, ensure_ascii=True, sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _variant_notes(variants):
|
||||||
|
return "; ".join(
|
||||||
|
f"{variant.get('key')} ({variant.get('status') or 'unknown'})"
|
||||||
|
for variant in variants
|
||||||
|
if variant.get("key")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SxCPHardcorePositionPool:
|
class SxCPHardcorePositionPool:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -268,7 +265,7 @@ class _SxCPKrea2POVVariantFilter:
|
|||||||
"hardcore_position_config",
|
"hardcore_position_config",
|
||||||
"selected_variant_keys",
|
"selected_variant_keys",
|
||||||
"selected_positions",
|
"selected_positions",
|
||||||
"prompt_cues",
|
"selected_variant_notes",
|
||||||
"summary",
|
"summary",
|
||||||
"variants_json",
|
"variants_json",
|
||||||
)
|
)
|
||||||
@@ -297,12 +294,11 @@ class _SxCPKrea2POVVariantFilter:
|
|||||||
parsed = json.loads(config)
|
parsed = json.loads(config)
|
||||||
selected_keys = parsed.get("krea2_variant_keys") or []
|
selected_keys = parsed.get("krea2_variant_keys") or []
|
||||||
selected_positions = parsed.get("positions") or []
|
selected_positions = parsed.get("positions") or []
|
||||||
prompt_cues = _join_variant_cues(variants, "prompt_cues")
|
|
||||||
return (
|
return (
|
||||||
config,
|
config,
|
||||||
",".join(str(key) for key in selected_keys),
|
",".join(str(key) for key in selected_keys),
|
||||||
",".join(str(position) for position in selected_positions),
|
",".join(str(position) for position in selected_positions),
|
||||||
prompt_cues,
|
_variant_notes(variants),
|
||||||
str(parsed.get("summary") or ""),
|
str(parsed.get("summary") or ""),
|
||||||
json.dumps(variants, ensure_ascii=True, sort_keys=True),
|
json.dumps(variants, ensure_ascii=True, sort_keys=True),
|
||||||
)
|
)
|
||||||
|
|||||||
+17
-1
@@ -705,6 +705,18 @@ def _hardcore_position_summary(config: dict[str, Any]) -> str:
|
|||||||
return hardcore_position_policy.hardcore_position_summary(config)
|
return hardcore_position_policy.hardcore_position_summary(config)
|
||||||
|
|
||||||
|
|
||||||
|
def _axis_values_with_krea2_variant_keys(
|
||||||
|
axis_values: dict[str, Any],
|
||||||
|
hardcore_position_config: dict[str, Any],
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
variant_keys = hardcore_position_config.get("krea2_variant_keys") if isinstance(hardcore_position_config, dict) else []
|
||||||
|
if not isinstance(variant_keys, list) or not variant_keys:
|
||||||
|
return axis_values
|
||||||
|
merged = dict(axis_values)
|
||||||
|
merged["krea2_variant_keys"] = [str(key) for key in variant_keys if str(key).strip()]
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
def build_hardcore_position_pool_json(
|
def build_hardcore_position_pool_json(
|
||||||
hardcore_position_config: str | dict[str, Any] | None = "",
|
hardcore_position_config: str | dict[str, Any] | None = "",
|
||||||
combine_mode: str = "replace",
|
combine_mode: str = "replace",
|
||||||
@@ -2459,6 +2471,10 @@ def _build_custom_row(
|
|||||||
action_family = action_route.action_family
|
action_family = action_route.action_family
|
||||||
|
|
||||||
text_fields = _row_text_fields(category, subcategory, item, style_config)
|
text_fields = _row_text_fields(category, subcategory, item, style_config)
|
||||||
|
formatter_axis_values = _axis_values_with_krea2_variant_keys(
|
||||||
|
item_axis_values,
|
||||||
|
parsed_hardcore_position_config,
|
||||||
|
)
|
||||||
|
|
||||||
assembly_request = row_assembly_policy.CustomRowAssemblyRequest(
|
assembly_request = row_assembly_policy.CustomRowAssemblyRequest(
|
||||||
row_number=row_number,
|
row_number=row_number,
|
||||||
@@ -2470,7 +2486,7 @@ def _build_custom_row(
|
|||||||
subject_type=subject_type,
|
subject_type=subject_type,
|
||||||
item_text=item_text,
|
item_text=item_text,
|
||||||
item_name=item_name,
|
item_name=item_name,
|
||||||
item_axis_values=item_axis_values,
|
item_axis_values=formatter_axis_values,
|
||||||
item_template_metadata=item_template_metadata,
|
item_template_metadata=item_template_metadata,
|
||||||
formatter_hints=item_formatter_hints,
|
formatter_hints=item_formatter_hints,
|
||||||
item_label=text_fields.item_label,
|
item_label=text_fields.item_label,
|
||||||
|
|||||||
+68
-2
@@ -8288,6 +8288,54 @@ def smoke_pov_oral_position_routes() -> None:
|
|||||||
for term in krea_terms:
|
for term in krea_terms:
|
||||||
_expect(term in prompt, f"{name} Krea prompt missing {term!r}: {prompt}")
|
_expect(term in prompt, f"{name} Krea prompt missing {term!r}: {prompt}")
|
||||||
|
|
||||||
|
top_variant_config = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPKrea2POVOralFilter"]().build(
|
||||||
|
"replace",
|
||||||
|
"",
|
||||||
|
include_blowjob_top_down_vertical_shaft=True,
|
||||||
|
)[0]
|
||||||
|
top_variant_pair = pb.build_insta_of_pair(
|
||||||
|
row_number=1,
|
||||||
|
start_index=1,
|
||||||
|
seed=3828,
|
||||||
|
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=top_variant_config,
|
||||||
|
location_config=_coworking_location_config(),
|
||||||
|
hardcore_camera_config=_orbit_camera(
|
||||||
|
horizontal_angle=45,
|
||||||
|
vertical_angle=0,
|
||||||
|
zoom=7.5,
|
||||||
|
subject_focus="action",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
_expect_pair(top_variant_pair, "pov_oral_top_view_variant_filter")
|
||||||
|
top_variant_row = top_variant_pair.get("hardcore_row") or {}
|
||||||
|
top_variant_config_row = top_variant_row.get("hardcore_position_config") or {}
|
||||||
|
_expect(
|
||||||
|
top_variant_config_row.get("krea2_variant_keys") == ["pov_blowjob_top_down_vertical_shaft"],
|
||||||
|
"Top-view POV filter lost exact variant key in row metadata",
|
||||||
|
)
|
||||||
|
top_axis_values = top_variant_row.get("item_axis_values") or {}
|
||||||
|
_expect(
|
||||||
|
top_axis_values.get("krea2_variant_keys") == ["pov_blowjob_top_down_vertical_shaft"],
|
||||||
|
"Top-view POV filter exact variant key did not reach formatter axis metadata",
|
||||||
|
)
|
||||||
|
top_krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(top_variant_pair), target="hardcore")
|
||||||
|
top_prompt = _expect_text("pov_oral_top_view_variant_filter.krea_prompt", top_krea.get("krea_prompt"), 60).lower()
|
||||||
|
_expect("nadir-angle standing male pov top-view oral position" in top_prompt, "Top-view variant prompt lost exact top-view route")
|
||||||
|
_expect("eye-level shot" not in top_prompt, f"Top-view variant prompt kept contradictory eye-level camera text: {top_prompt}")
|
||||||
|
_expect("tongue extended toward genitals" not in top_prompt, f"Top-view variant prompt kept contradictory tongue-extension expression: {top_prompt}")
|
||||||
|
|
||||||
side_body_item = "side-lying oral position while blowjob with lips wrapped around the viewer's penis"
|
side_body_item = "side-lying oral position while blowjob with lips wrapped around the viewer's penis"
|
||||||
side_body_axis = {"position": "side-lying oral position"}
|
side_body_axis = {"position": "side-lying oral position"}
|
||||||
side_body_role_graph = hardcore_role_oral.build_oral_role_graph(
|
side_body_role_graph = hardcore_role_oral.build_oral_role_graph(
|
||||||
@@ -10943,7 +10991,25 @@ def smoke_node_hardcore_position_registration() -> None:
|
|||||||
"include_doggy_top_down_rear_entry" not in oral_inputs,
|
"include_doggy_top_down_rear_entry" not in oral_inputs,
|
||||||
"POV Oral Filter should not expose penetration atlas checkboxes",
|
"POV Oral Filter should not expose penetration atlas checkboxes",
|
||||||
)
|
)
|
||||||
doggy_config, doggy_keys, doggy_positions, doggy_cues, doggy_summary, doggy_variants_json = penetration_filter().build(
|
top_config, top_keys, top_positions, top_notes, top_summary, _top_variants_json = oral_filter().build(
|
||||||
|
"replace",
|
||||||
|
"",
|
||||||
|
include_blowjob_top_down_vertical_shaft=True,
|
||||||
|
)
|
||||||
|
parsed_top_config = json.loads(top_config)
|
||||||
|
_expect(top_keys == "pov_blowjob_top_down_vertical_shaft", "POV Oral Filter returned wrong exact top-view variant key")
|
||||||
|
_expect(
|
||||||
|
parsed_top_config.get("krea2_variant_keys") == ["pov_blowjob_top_down_vertical_shaft"],
|
||||||
|
"POV Oral Filter lost exact top-view variant metadata",
|
||||||
|
)
|
||||||
|
_expect("kneeling" in top_positions, "POV Oral Filter lost top-view route position")
|
||||||
|
_expect(
|
||||||
|
"nadir-angle" not in top_notes and "viewer looks almost straight down" not in top_notes,
|
||||||
|
"POV Oral Filter should not emit raw atlas prompt prose as a connectable text output",
|
||||||
|
)
|
||||||
|
_expect("variants=pov_blowjob_top_down_vertical_shaft" in top_summary, "POV Oral Filter summary lost top-view variant key")
|
||||||
|
|
||||||
|
doggy_config, doggy_keys, doggy_positions, doggy_notes, doggy_summary, doggy_variants_json = penetration_filter().build(
|
||||||
"replace",
|
"replace",
|
||||||
"",
|
"",
|
||||||
include_doggy_top_down_rear_entry=True,
|
include_doggy_top_down_rear_entry=True,
|
||||||
@@ -10957,7 +11023,7 @@ def smoke_node_hardcore_position_registration() -> None:
|
|||||||
)
|
)
|
||||||
_expect(doggy_keys == "pov_doggy_top_down_rear_entry", "POV Penetration Filter returned wrong selected variant keys")
|
_expect(doggy_keys == "pov_doggy_top_down_rear_entry", "POV Penetration Filter returned wrong selected variant keys")
|
||||||
_expect(doggy_positions == "doggy", "POV Penetration Filter returned wrong selected positions")
|
_expect(doggy_positions == "doggy", "POV Penetration Filter returned wrong selected positions")
|
||||||
_expect("top-down" in doggy_cues, "POV Penetration Filter lost prompt cues output")
|
_expect("pov_doggy_top_down_rear_entry" in doggy_notes and "top-down POV" not in doggy_notes, "POV Penetration Filter should emit compact variant notes, not raw prompt cues")
|
||||||
_expect("variants=pov_doggy_top_down_rear_entry" in doggy_summary, "POV Penetration Filter summary lost selected variant")
|
_expect("variants=pov_doggy_top_down_rear_entry" in doggy_summary, "POV Penetration Filter summary lost selected variant")
|
||||||
_expect(json.loads(doggy_variants_json)[0].get("key") == "pov_doggy_top_down_rear_entry", "POV Penetration Filter returned wrong variant JSON")
|
_expect(json.loads(doggy_variants_json)[0].get("key") == "pov_doggy_top_down_rear_entry", "POV Penetration Filter returned wrong variant JSON")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user