Promote multi-person hardcore action routing

This commit is contained in:
2026-06-27 19:19:37 +02:00
parent 658743d876
commit 2b41a82869
6 changed files with 150 additions and 7 deletions
+68 -1
View File
@@ -4015,6 +4015,10 @@ def smoke_caption_policy() -> None:
)
row = {"action_family": "oral", "position_family": ""}
_expect(caption_policy.metadata_action_label(row) == "oral action", "Caption action-family label changed")
row = {"action_family": "threesome", "position_family": ""}
_expect(caption_policy.metadata_action_label(row) == "three-person action", "Caption threesome action-family label changed")
row = {"action_family": "group", "position_family": ""}
_expect(caption_policy.metadata_action_label(row) == "group action", "Caption group action-family label changed")
row = {"action_family": "oral", "position_family": "Anal"}
_expect(caption_naturalizer._metadata_action_label(row) == "anal action", "Caption position-family label priority changed")
browsing_caption, browsing_method = caption_naturalizer.naturalize_caption(
@@ -4913,6 +4917,14 @@ def smoke_hardcore_position_config_policy() -> None:
category_template_metadata.template_action_family({"action_family": "anal sex"}) == "anal",
"Template action-family normalizer should accept anal aliases",
)
_expect(
category_template_metadata.template_action_family({"action_family": "three way"}) == "threesome",
"Template action-family normalizer should accept threesome aliases",
)
_expect(
category_template_metadata.template_action_family({"action_family": "group sex"}) == "group",
"Template action-family normalizer should accept group aliases",
)
_expect(
category_template_metadata.template_position_family({"position_family": "penetration"}) == "penetrative",
"Template position-family normalizer should accept action-style aliases",
@@ -4965,6 +4977,26 @@ def smoke_hardcore_position_config_policy() -> None:
_expect(filtered.get("allow_penetration") is False, "Hardcore outercourse focus should disable penetration")
_expect("outercourse_sex" in hardcore_position_config.hardcore_allowed_subcategory_slugs(filtered), "Allowed subcategories lost outercourse")
_expect("oral_sex" not in hardcore_position_config.hardcore_allowed_subcategory_slugs(filtered), "Allowed subcategories should exclude oral")
strict_threesome = json.loads(
pb.build_hardcore_action_filter_json(
hardcore_position_config=pb.build_hardcore_position_pool_json(family="threesome"),
focus="threesome_only",
allow_toys=False,
allow_double=False,
allow_penetration=False,
allow_foreplay=False,
allow_interaction=False,
allow_manual=False,
allow_oral=False,
allow_outercourse=False,
allow_anal=False,
allow_climax=False,
)
)
_expect(
hardcore_position_config.hardcore_allowed_subcategory_slugs(strict_threesome) == {"threesomes"},
"Specific hardcore family filter should not widen to the full pool when boolean filters empty it",
)
action_only = json.loads(
hardcore_position_config.build_hardcore_action_filter_json(
focus="outercourse_only",
@@ -5062,6 +5094,14 @@ def smoke_hardcore_position_config_policy() -> None:
"generic contact",
)
_expect(source_action_family == "outercourse", "Source action-family fallback should accept hyphenated source aliases")
_expect(
hardcore_action_metadata.source_hardcore_action_family("threesome", "", "three-body contact") == "threesome",
"Source action-family fallback should accept threesome source family",
)
_expect(
hardcore_action_metadata.source_hardcore_action_family("group", "", "group sex contact") == "group",
"Source action-family fallback should accept group source family",
)
default_action_route = row_route_metadata.resolve_action_position_route(
is_pose_category=True,
subcategory={"slug": "anal_double_penetration"},
@@ -5550,6 +5590,31 @@ def smoke_hardcore_category_routes() -> None:
_expect(sdxl_tag in (sdxl.get("sdxl_prompt") or "").lower(), f"{name} SDXL prompt did not include family tag {sdxl_tag!r}")
caption, _method = caption_naturalizer.naturalize_caption("", metadata_json=_json(row), trigger=Trigger, include_trigger=True)
_expect(caption_label in caption.lower(), f"{name} caption did not include family label {caption_label!r}")
multi_cases = [
("hardcore_threesome", "Threesomes", "threesome_only", "threesome", {"threesome", "toy_double"}, "threesome", "three-person action", 1, 2),
("hardcore_group", "Group sex and orgy", "group_only", "group", {"group", "toy_double"}, "group sex", "group action", 2, 2),
]
for index, (name, subcategory, focus, position_family, action_families, sdxl_tag, caption_label, women_count, men_count) in enumerate(multi_cases, start=1151):
subjects = ["woman"] * women_count + ["man"] * men_count
row = _prompt_row(
name=name,
category="Hardcore sexual poses",
subcategory=subcategory,
seed=index,
character_cast=_character_cast_subjects(subjects),
women_count=women_count,
men_count=men_count,
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(row.get("position_family") == position_family, f"{name} position_family mismatch: {row.get('position_family')}")
_expect(row.get("action_family") in action_families, f"{name} action_family mismatch: {row.get('action_family')}")
_expect_formatter_outputs(row, name, target="single")
sdxl = sdxl_formatter.format_sdxl_prompt("", metadata_json=_json(row), target="single", trigger=SdxlTrigger, prepend_trigger=True)
_expect(sdxl_tag in (sdxl.get("sdxl_prompt") or "").lower(), f"{name} SDXL prompt did not include family tag {sdxl_tag!r}")
caption, _method = caption_naturalizer.naturalize_caption("", metadata_json=_json(row), trigger=Trigger, include_trigger=True)
_expect(caption_label in caption.lower(), f"{name} caption did not include family label {caption_label!r}")
annotated_row = None
for seed in range(1801, 1841):
row = _prompt_row(
@@ -7071,6 +7136,8 @@ def smoke_fallback_role_graph_routes() -> None:
)
_expect_custom_row(row, name)
_expect(row.get("position_family") == family, f"{name} position_family mismatch: {row.get('position_family')}")
if family == "threesome":
_expect(row.get("action_family") == "threesome", f"{name} action_family should be threesome")
_expect(position_key in (row.get("position_keys") or []), f"{name} lost position key {position_key!r}")
role_graph = _expect_text(f"{name}.source_role_graph", row.get("source_role_graph"), 30).lower()
for term in role_terms:
@@ -7844,7 +7911,7 @@ def smoke_seed_config_policy() -> None:
def smoke_prompt_route_simulation_policy() -> None:
report = prompt_route_simulation.run_simulation(seed=3901, include_prompts=False)
summary = report.get("summary") or {}
_expect(summary.get("cases") == 11, "Prompt route simulation case count changed unexpectedly")
_expect(summary.get("cases") == 13, "Prompt route simulation case count changed unexpectedly")
_expect(summary.get("axis_checks") == 6, "Prompt route simulation lost axis check coverage")
_expect(summary.get("issues") == 0, f"Prompt route simulation reported issues: {report.get('issues')}")
cases = {case.get("name"): case for case in report.get("cases") or []}