Align outercourse action routing

This commit is contained in:
2026-06-27 16:15:27 +02:00
parent ff6195473b
commit 002c3b79d4
10 changed files with 393 additions and 67 deletions
+70 -8
View File
@@ -48,10 +48,12 @@ import hardcore_action_metadata # noqa: E402
import hardcore_position_config # noqa: E402
import __init__ as sxcp_nodes # noqa: E402
import generation_profile_config # noqa: E402
import hardcore_role_outercourse # noqa: E402
import index_switch_policy # noqa: E402
import node_tooltips # noqa: E402
import krea_cast # noqa: E402
import krea_action_details # noqa: E402
import krea_action_context # noqa: E402
import krea_configured_cast_formatter # noqa: E402
import krea_format_route # noqa: E402
import krea_formatter # noqa: E402
@@ -67,6 +69,7 @@ import pair_clothing # noqa: E402
import pair_rows # noqa: E402
import prompt_hygiene # noqa: E402
import prompt_builder as pb # noqa: E402
import outercourse_action_policy # noqa: E402
import pov_policy # noqa: E402
import row_normalization # noqa: E402
import row_assembly # noqa: E402
@@ -1181,6 +1184,60 @@ def smoke_krea_action_details_policy() -> None:
)
def smoke_outercourse_action_policy() -> None:
_expect(
outercourse_action_policy.infer_outercourse_action_kind("kneeling boobjob position")
== outercourse_action_policy.OUTERCOURSE_BOOBJOB,
"Outercourse classifier lost boobjob position detection",
)
_expect(
outercourse_action_policy.infer_outercourse_action_kind("bent-over balls-licking position")
== outercourse_action_policy.OUTERCOURSE_TESTICLE,
"Outercourse classifier lost testicle/balls position detection",
)
_expect(
outercourse_action_policy.infer_outercourse_action_kind("tongue runs along the underside of the penis")
== outercourse_action_policy.OUTERCOURSE_PENIS_LICKING,
"Outercourse classifier lost penis-licking detail detection",
)
_expect(
outercourse_action_policy.infer_outercourse_action_kind("two-handed handjob with thumb and fingers around the penis")
== outercourse_action_policy.OUTERCOURSE_HANDJOB,
"Outercourse classifier lost handjob detection",
)
_expect(
outercourse_action_policy.infer_outercourse_action_kind("footjob with toes curled around the penis")
== outercourse_action_policy.OUTERCOURSE_FOOTJOB,
"Outercourse classifier lost footjob detection",
)
axis_text = krea_action_context.axis_values_text(
{
"outer_act": "handjob with one hand wrapped around the penis",
"contact_detail": "hand wrapped around the penis shaft with the glans visible",
"visibility": "hand and penis centered in frame",
}
)
_expect("handjob" in axis_text and "hand and penis" in axis_text, "Krea action context lost outercourse axes")
role_graph = hardcore_role_outercourse.build_outercourse_role_graph(
"Woman A",
"Man A",
"testicle sucking with lips around the balls",
{"position": "bent-over testicle-sucking position"},
["Man A"],
)
lower_role = role_graph.lower()
_expect("face below the pov viewer's penis at testicle height" in lower_role, "POV testicle role graph lost low-head geometry")
_expect("penis points upward" in lower_role, "POV testicle role graph lost foreground penis geometry")
deduped = krea_action_details.dedupe_outercourse_detail(
"testicle sucking with lips around the balls, balls and mouth contact visible, wet lips and tongue contact",
role_graph,
"testicle sucking with lips around the balls",
{"position": "bent-over testicle-sucking position"},
).lower()
_expect("testicle" not in deduped and "balls and mouth" not in deduped, "Krea outercourse dedupe kept redundant testicle clauses")
_expect("wet lips" in deduped, "Krea outercourse dedupe removed useful texture clause")
def smoke_krea_row_fields_policy() -> None:
row = {
"subject_type": "configured_cast",
@@ -5503,26 +5560,26 @@ def smoke_pov_outercourse_position_routes() -> None:
(
"pov_outercourse_boobjob",
"boobjob",
("breasts tightly around", "glans sits just below"),
("press her breasts tightly around", "glans just below", "penis shaft"),
("breasts inward around", "directly above the glans"),
("push her breasts inward around", "directly above the glans", "held between her breasts"),
),
(
"pov_outercourse_testicle",
"testicle_sucking",
("mouth and tongue on the pov viewer's balls", "penis points upward"),
("mouth and tongue licking", "balls", "penis points upward"),
("face below the pov viewer's penis at testicle height", "penis points upward"),
("face is below the viewer's penis at testicle height", "mouth and tongue licking", "penis points upward"),
),
(
"pov_outercourse_penis_licking",
"penis_licking",
("head low under the pov viewer's penis", "tongue running along"),
("tongue runs along", "penis shaft", "glans"),
("head low under the pov viewer's penis", "tongue touches the underside"),
("tongue touches the underside", "glans at the tip", "viewer"),
),
(
"pov_outercourse_handjob",
"handjob",
("one hand wrapped around the pov viewer's penis", "strokes toward the glans"),
("one hand wraps around", "penis shaft", "strokes toward the glans"),
("one hand grips and strokes the pov viewer's penis", "strokes toward the glans"),
("one hand grips and strokes the viewer's penis", "thumb and fingers", "strokes toward the glans"),
),
(
"pov_outercourse_footjob",
@@ -5572,6 +5629,10 @@ def smoke_pov_outercourse_position_routes() -> None:
_expect("camera:" not in krea.get("krea_prompt", ""), f"{name} Krea prompt emitted normal third-person camera directive")
for term in krea_terms:
_expect(term in prompt, f"{name} Krea prompt missing {term!r}: {prompt}")
if position_key == "handjob":
_expect("behind the penis shaft" not in prompt, f"{name} Krea prompt kept vague shaft-only wording: {prompt}")
if position_key == "testicle_sucking":
_expect("head is tucked under the penis shaft" not in prompt, f"{name} Krea prompt kept high-head testicle wording: {prompt}")
def smoke_pov_oral_position_routes() -> None:
@@ -7636,6 +7697,7 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
("builder_config_route_policy", smoke_builder_config_route_policy),
("krea_normal_row_routes", smoke_krea_normal_row_routes),
("krea_action_details_policy", smoke_krea_action_details_policy),
("outercourse_action_policy", smoke_outercourse_action_policy),
("krea_row_fields_policy", smoke_krea_row_fields_policy),
("location_config_policy", smoke_location_config_policy),
("row_location_policy", smoke_row_location_policy),