Cover Krea action POV smoke routes

This commit is contained in:
2026-06-26 15:17:18 +02:00
parent b82cf3fbbf
commit a4a8a7a28e
6 changed files with 91 additions and 8 deletions
+13 -7
View File
@@ -57,7 +57,9 @@ It should only handle route-agnostic cleanup:
It must not make semantic decisions such as sexual action positioning, POV
geometry, clothing state, or model-specific tag weighting. Those stay in the
route-specific owner.
route-specific owner. It also preserves ordinary words such as `composition`
inside normal sentences; empty field-label cleanup is limited to standalone
labels.
Current integration points:
@@ -93,6 +95,8 @@ Already isolated:
- camera-scene prose and coworking composition adaptation live in
`scene_camera_adapters.py`; `prompt_builder.py` still owns camera config
parsing and row mutation.
- shared hardcore environment-anchor cleanup normalizes malformed pool joins
such as `on against a wall` before metadata reaches formatter routes.
### Pair / Adapter Layer
@@ -248,10 +252,12 @@ Near-term:
formatting across built-in rows, hardcore rows, same-cast pairs, and POV
pairs.
- Cover camera-scene preservation through `tools/prompt_smoke.py` for single
rows, split soft/hard pair cameras, and POV camera-scene routing. Expand it
rows, split soft/hard pair cameras, and POV camera-scene routing.
- Cover config-node routing through `tools/prompt_smoke.py` for category, cast,
generation profile, seed lock, camera, location theme, and composition config.
Expand it next for close foreplay and POV penetration.
- Cover close foreplay and POV penetration Krea routes so raw labels, invalid
surface grammar, normal third-person camera text, and composition punctuation
drift are caught.
Medium-term:
@@ -310,8 +316,8 @@ Medium-term:
## Recommended Next Passes
1. Expand `tools/prompt_smoke.py` with close foreplay and POV penetration
fixtures.
2. Split Krea action/POV/clothing helpers into separate modules.
3. Split `__init__.py` node classes by family after behavior is covered by smoke
1. Split Krea action/POV/clothing helpers into separate modules.
2. Split `__init__.py` node classes by family after behavior is covered by smoke
checks.
3. Add metadata fields such as `action_family` / `position_family` to reduce
keyword guessing in hardcore filters and formatter dispatch.
+5
View File
@@ -687,6 +687,11 @@ pair metadata through the core Python APIs, then verifies:
collapsing to the same camera phrase;
- POV camera-scene directives suppress normal third-person camera text while
preserving first-person spatial layout;
- Krea close-interaction routes keep rewritten action wording, avoid raw
builder labels, and catch invalid surface joins such as `on against a wall`;
- Krea POV penetration routes keep first-person position anchors, suppress
normal camera text, and preserve composition punctuation before the style
suffix;
- expression-disabled rows do not fall back to generated expression text.
## Editing Cheatsheet
+1
View File
@@ -47,6 +47,7 @@ def _clean(value: Any) -> str:
HARDCORE_ENVIRONMENT_ANCHOR_REPLACEMENTS = (
(r"\bon against a wall\b", "against a wall"),
(r"\bstacked bodies on the bed\b", "close body alignment"),
(r"\bstacked bodies with close body alignment\b", "close body alignment"),
(r"\boverhead tangled-body anal frame\b", "overhead rear-entry anal frame"),
+1
View File
@@ -966,6 +966,7 @@ def _heuristic_cast_compatible(text: str, women_count: int, men_count: int) -> b
HARDCORE_ENVIRONMENT_ANCHOR_REPLACEMENTS = (
(r"\bon against a wall\b", "against a wall"),
(r"\bstacked bodies on the bed\b", "close body alignment"),
(r"\bstacked bodies with close body alignment\b", "close body alignment"),
(r"\boverhead tangled-body anal frame\b", "overhead rear-entry anal frame"),
+1 -1
View File
@@ -51,7 +51,7 @@ def _strip_empty_fields(text: str) -> str:
labels = "|".join(re.escape(label) for label in EMPTY_FIELD_LABELS)
text = re.sub(rf"\b(?:{labels})\s*:\s*[.,;]", "", text, flags=re.IGNORECASE)
text = re.sub(rf"\b(?:{labels}):\s*(?=\.|,|;|$)", "", text, flags=re.IGNORECASE)
text = re.sub(rf"\b(?:{labels})\.(?=\s|$)", "", text, flags=re.IGNORECASE)
text = re.sub(rf"(^|(?<=[.!?])\s+)(?:{labels})\.(?=\s|$)", r"\1", text, flags=re.IGNORECASE)
text = re.sub(rf"\b(?:{labels}):\s*(?:none|null|n/a)\b[.,;]?", "", text, flags=re.IGNORECASE)
return clean_spacing(text)
+70
View File
@@ -387,6 +387,32 @@ def smoke_hardcore_category_routes() -> None:
_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",
@@ -553,6 +579,48 @@ def smoke_pov_camera_scene() -> None:
_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",
@@ -584,10 +652,12 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
("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),
("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),
]