Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7381b9d51 | |||
| c95bb30a22 | |||
| b8d164a3da |
@@ -45,6 +45,22 @@ Version: `2026-06-30-generated-route-validation-positive-channel-cleanup`
|
|||||||
code path before closing the category. Manual prompt-axis wins are not
|
code path before closing the category. Manual prompt-axis wins are not
|
||||||
enough; the generated route can still drop the key contact hierarchy or add
|
enough; the generated route can still drop the key contact hierarchy or add
|
||||||
limiting positive-channel wording.
|
limiting positive-channel wording.
|
||||||
|
14. Treat the final prompt that Krea receives and the rendered generator images
|
||||||
|
as the source of truth. Tests are guardrails for known failures, not proof
|
||||||
|
that the prompt will render the intended pose. If a test passes while the
|
||||||
|
rendered image or prompt audit shows drift, update the test and the method
|
||||||
|
rather than trusting the test.
|
||||||
|
15. Atlas/catalog prompt wording must use direct visual prompt sentences. Do
|
||||||
|
not send option-list wording such as `or`, `may`, `optionally`, or `either`
|
||||||
|
in pose cues, and do not append meta instructions such as `keep the visible
|
||||||
|
partner...` or generic camera-layout prose to atlas routes. Krea2 is not an
|
||||||
|
instruction-following LLM in this loop; prompt text should describe the
|
||||||
|
image, not explain a policy.
|
||||||
|
16. Do not promote generator edits from a few isolated renders unless the final
|
||||||
|
generated prompt is structurally wrong before rendering. For pose wording
|
||||||
|
changes, collect prompt/image evidence across multiple women, source cases,
|
||||||
|
and seeds when feasible, then patch only the repeated generator-safe
|
||||||
|
hierarchy. Keep early wins as prompt-guide or provisional evidence.
|
||||||
|
|
||||||
## Promotion Gates
|
## Promotion Gates
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ METADATA_AXIS_KEYS = {
|
|||||||
"position_key",
|
"position_key",
|
||||||
"position_keys",
|
"position_keys",
|
||||||
"krea2_variant_keys",
|
"krea2_variant_keys",
|
||||||
|
"krea2_prompt_variant_indices",
|
||||||
"restored_prompt_axes",
|
"restored_prompt_axes",
|
||||||
}
|
}
|
||||||
ACTION_CONTEXT_PRIORITY = (
|
ACTION_CONTEXT_PRIORITY = (
|
||||||
|
|||||||
@@ -76,6 +76,33 @@ def get_variant(key: str, *, path: str | Path | None = None) -> dict[str, Any]:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def _cue_list(value: Any) -> list[str]:
|
||||||
|
if isinstance(value, dict):
|
||||||
|
value = value.get("prompt_cues") or value.get("cues")
|
||||||
|
if not isinstance(value, list):
|
||||||
|
return []
|
||||||
|
return [str(cue) for cue in value if str(cue).strip()]
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_cue_sets(variant_or_key: dict[str, Any] | str) -> list[list[str]]:
|
||||||
|
variant = get_variant(variant_or_key) if isinstance(variant_or_key, str) else dict(variant_or_key or {})
|
||||||
|
if not variant:
|
||||||
|
return []
|
||||||
|
cue_sets: list[list[str]] = []
|
||||||
|
baseline = _cue_list(variant.get("prompt_cues"))
|
||||||
|
if baseline:
|
||||||
|
cue_sets.append(baseline)
|
||||||
|
for cue_set in variant.get("prompt_variant_cues") or []:
|
||||||
|
cues = _cue_list(cue_set)
|
||||||
|
if cues:
|
||||||
|
cue_sets.append(cues)
|
||||||
|
if not cue_sets:
|
||||||
|
fallback = str(variant.get("canonical_geometry") or "").strip()
|
||||||
|
if fallback:
|
||||||
|
cue_sets.append([fallback])
|
||||||
|
return cue_sets
|
||||||
|
|
||||||
|
|
||||||
def reference_paths(key: str, *, path: str | Path | None = None) -> list[Path]:
|
def reference_paths(key: str, *, path: str | Path | None = None) -> list[Path]:
|
||||||
catalog = load_catalog(path)
|
catalog = load_catalog(path)
|
||||||
atlas_root = Path(str(catalog.get("atlas_root") or ""))
|
atlas_root = Path(str(catalog.get("atlas_root") or ""))
|
||||||
@@ -90,4 +117,3 @@ def reference_paths(key: str, *, path: str | Path | None = None) -> list[Path]:
|
|||||||
continue
|
continue
|
||||||
paths.append(atlas_root / ref_path)
|
paths.append(atlas_root / ref_path)
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
|||||||
+19
-6
@@ -97,6 +97,16 @@ def _has_krea2_atlas_variant(row: dict[str, Any]) -> bool:
|
|||||||
return any(krea2_pose_variant_catalog.get_variant(key) for key in _krea2_variant_keys(row))
|
return any(krea2_pose_variant_catalog.get_variant(key) for key in _krea2_variant_keys(row))
|
||||||
|
|
||||||
|
|
||||||
|
def _restores_krea2_prompt_axis(row: dict[str, Any], axis_name: str) -> bool:
|
||||||
|
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 {}
|
||||||
|
restored_axes = [
|
||||||
|
*_list_values(config.get("restore_prompt_axes")),
|
||||||
|
*_list_values(axis_values.get("restored_prompt_axes")),
|
||||||
|
]
|
||||||
|
return axis_name in restored_axes
|
||||||
|
|
||||||
|
|
||||||
def _has_krea2_top_down_variant(row: dict[str, Any]) -> bool:
|
def _has_krea2_top_down_variant(row: dict[str, Any]) -> bool:
|
||||||
for key in _krea2_variant_keys(row):
|
for key in _krea2_variant_keys(row):
|
||||||
variant = krea2_pose_variant_catalog.get_variant(key)
|
variant = krea2_pose_variant_catalog.get_variant(key)
|
||||||
@@ -214,6 +224,14 @@ def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairForma
|
|||||||
)
|
)
|
||||||
hard_has_atlas_variant = _has_krea2_atlas_variant(hard)
|
hard_has_atlas_variant = _has_krea2_atlas_variant(hard)
|
||||||
hard_output_composition = "" if hard_has_atlas_variant else deps.pov_composition_text(hard_composition, pov_labels)
|
hard_output_composition = "" if hard_has_atlas_variant else deps.pov_composition_text(hard_composition, pov_labels)
|
||||||
|
hard_restores_clothing = hard_has_atlas_variant and _restores_krea2_prompt_axis(hard, "clothing_detail")
|
||||||
|
hard_clothing = deps.natural_label_text(
|
||||||
|
deps.filter_pov_labeled_clauses(
|
||||||
|
deps.natural_clothing_state(row.get("hardcore_clothing_state"), hard_action),
|
||||||
|
pov_labels,
|
||||||
|
),
|
||||||
|
hard_labels,
|
||||||
|
)
|
||||||
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
|
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
|
||||||
soft_output_composition = deps.pov_composition_text(soft.get("composition"), pov_labels if same_soft_cast else [])
|
soft_output_composition = deps.pov_composition_text(soft.get("composition"), pov_labels if same_soft_cast else [])
|
||||||
soft_cast_presence = deps.softcore_cast_presence_phrase(
|
soft_cast_presence = deps.softcore_cast_presence_phrase(
|
||||||
@@ -284,12 +302,7 @@ def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairForma
|
|||||||
hard_cast_prose,
|
hard_cast_prose,
|
||||||
hard_action,
|
hard_action,
|
||||||
deps.pov_camera_phrase(pov_labels),
|
deps.pov_camera_phrase(pov_labels),
|
||||||
""
|
hard_clothing if (not hard_has_atlas_variant or hard_restores_clothing) else "",
|
||||||
if hard_has_atlas_variant
|
|
||||||
else deps.natural_label_text(
|
|
||||||
deps.filter_pov_labeled_clauses(deps.natural_clothing_state(row.get("hardcore_clothing_state"), hard_action), pov_labels),
|
|
||||||
hard_labels,
|
|
||||||
),
|
|
||||||
f"set in {hard_scene}" if hard_scene else "",
|
f"set in {hard_scene}" if hard_scene else "",
|
||||||
hard_camera_scene,
|
hard_camera_scene,
|
||||||
deps.expression_phrase(hard_expression),
|
deps.expression_phrase(hard_expression),
|
||||||
|
|||||||
+35
-2
@@ -105,14 +105,47 @@ def _unique_texts(values: list[Any]) -> list[str]:
|
|||||||
return texts
|
return texts
|
||||||
|
|
||||||
|
|
||||||
|
def _restored_visible_details(axis_values: dict[str, Any]) -> list[str]:
|
||||||
|
restored_details = _list_values(axis_values.get("restored_prompt_details"))
|
||||||
|
restored_axes = _list_values(axis_values.get("restored_prompt_axes"))
|
||||||
|
if restored_axes and len(restored_axes) == len(restored_details):
|
||||||
|
return _unique_texts(
|
||||||
|
[
|
||||||
|
detail
|
||||||
|
for axis, detail in zip(restored_axes, restored_details)
|
||||||
|
if axis != "clothing_detail"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
clothing_detail = _clean(axis_values.get("clothing_detail")).lower()
|
||||||
|
return _unique_texts(
|
||||||
|
[
|
||||||
|
detail
|
||||||
|
for detail in restored_details
|
||||||
|
if not clothing_detail or _clean(detail).lower() != clothing_detail
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _krea2_atlas_variant_sentence(axis_values: Any) -> str:
|
def _krea2_atlas_variant_sentence(axis_values: Any) -> str:
|
||||||
variant = _selected_krea2_atlas_variant(axis_values)
|
variant = _selected_krea2_atlas_variant(axis_values)
|
||||||
if not variant:
|
if not variant:
|
||||||
return ""
|
return ""
|
||||||
cues = _unique_texts(list(variant.get("prompt_cues") or []) or [variant.get("canonical_geometry")])
|
cue_sets = krea2_pose_variant_catalog.prompt_cue_sets(variant)
|
||||||
|
selected_index = 0
|
||||||
|
if isinstance(axis_values, dict):
|
||||||
|
indices = axis_values.get("krea2_prompt_variant_indices")
|
||||||
|
if isinstance(indices, dict):
|
||||||
|
try:
|
||||||
|
selected_index = int(indices.get(str(variant.get("key") or ""), 0))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
selected_index = 0
|
||||||
|
if selected_index < 0 or selected_index >= len(cue_sets):
|
||||||
|
selected_index = 0
|
||||||
|
cues = _unique_texts(cue_sets[selected_index] if cue_sets else [variant.get("canonical_geometry")])
|
||||||
sentence = _clean(". ".join(cues)).rstrip(".")
|
sentence = _clean(". ".join(cues)).rstrip(".")
|
||||||
if isinstance(axis_values, dict):
|
if isinstance(axis_values, dict):
|
||||||
restored_details = _unique_texts(_list_values(axis_values.get("restored_prompt_details")))
|
restored_details = _restored_visible_details(axis_values)
|
||||||
if restored_details:
|
if restored_details:
|
||||||
sentence = f"{sentence}. Additional visible detail: {'; '.join(restored_details)}"
|
sentence = f"{sentence}. Additional visible detail: {'; '.join(restored_details)}"
|
||||||
return sentence
|
return sentence
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ try:
|
|||||||
from . import generate_prompt_batches as g
|
from . import generate_prompt_batches as g
|
||||||
from . import generation_profile_config as generation_profile_policy
|
from . import generation_profile_config as generation_profile_policy
|
||||||
from . import hardcore_position_config as hardcore_position_policy
|
from . import hardcore_position_config as hardcore_position_policy
|
||||||
|
from . import krea2_pose_variant_catalog
|
||||||
from . import location_config as location_policy
|
from . import location_config as location_policy
|
||||||
from . import pair_builder
|
from . import pair_builder
|
||||||
from . import pair_cast
|
from . import pair_cast
|
||||||
@@ -76,6 +77,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
|
|||||||
import generate_prompt_batches as g
|
import generate_prompt_batches as g
|
||||||
import generation_profile_config as generation_profile_policy
|
import generation_profile_config as generation_profile_policy
|
||||||
import hardcore_position_config as hardcore_position_policy
|
import hardcore_position_config as hardcore_position_policy
|
||||||
|
import krea2_pose_variant_catalog
|
||||||
import location_config as location_policy
|
import location_config as location_policy
|
||||||
import pair_builder
|
import pair_builder
|
||||||
import pair_cast
|
import pair_cast
|
||||||
@@ -717,6 +719,30 @@ def _axis_values_with_krea2_variant_keys(
|
|||||||
return merged
|
return merged
|
||||||
|
|
||||||
|
|
||||||
|
def _axis_values_with_krea2_prompt_variant_indices(
|
||||||
|
axis_values: dict[str, Any],
|
||||||
|
*,
|
||||||
|
seed_config: dict[str, int],
|
||||||
|
seed: int,
|
||||||
|
row_number: int,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
variant_keys = axis_values.get("krea2_variant_keys") if isinstance(axis_values, dict) else []
|
||||||
|
if not isinstance(variant_keys, list) or not variant_keys:
|
||||||
|
return axis_values
|
||||||
|
rng = seed_policy.axis_rng(seed_config, "pose", seed, row_number)
|
||||||
|
indices: dict[str, int] = {}
|
||||||
|
for key in variant_keys:
|
||||||
|
variant = krea2_pose_variant_catalog.get_variant(str(key))
|
||||||
|
cue_sets = krea2_pose_variant_catalog.prompt_cue_sets(variant)
|
||||||
|
if len(cue_sets) > 1:
|
||||||
|
indices[str(key)] = rng.randrange(len(cue_sets))
|
||||||
|
if not indices:
|
||||||
|
return axis_values
|
||||||
|
merged = dict(axis_values)
|
||||||
|
merged["krea2_prompt_variant_indices"] = indices
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
def _axis_values_with_hardcore_route_metadata(
|
def _axis_values_with_hardcore_route_metadata(
|
||||||
axis_values: dict[str, Any],
|
axis_values: dict[str, Any],
|
||||||
*,
|
*,
|
||||||
@@ -2387,6 +2413,12 @@ def _build_custom_row(
|
|||||||
item_axis_values,
|
item_axis_values,
|
||||||
parsed_hardcore_position_config,
|
parsed_hardcore_position_config,
|
||||||
)
|
)
|
||||||
|
item_axis_values = _axis_values_with_krea2_prompt_variant_indices(
|
||||||
|
item_axis_values,
|
||||||
|
seed_config=seed_config,
|
||||||
|
seed=seed,
|
||||||
|
row_number=row_number,
|
||||||
|
)
|
||||||
item_template_metadata = dict(category_route.item_template_metadata)
|
item_template_metadata = dict(category_route.item_template_metadata)
|
||||||
item_formatter_hints = dict(category_route.formatter_hints)
|
item_formatter_hints = dict(category_route.formatter_hints)
|
||||||
is_pose_category = category_route.is_pose_category
|
is_pose_category = category_route.is_pose_category
|
||||||
|
|||||||
+100
-5
@@ -6762,8 +6762,13 @@ def smoke_krea2_pov_pose_variant_catalog() -> None:
|
|||||||
refs = variant.get("reference_images")
|
refs = variant.get("reference_images")
|
||||||
_expect(isinstance(prompt_cues, list) and prompt_cues, f"{key} has no prompt cues")
|
_expect(isinstance(prompt_cues, list) and prompt_cues, f"{key} has no prompt cues")
|
||||||
_expect(isinstance(avoid_cues, list) and avoid_cues, f"{key} has no avoid cues")
|
_expect(isinstance(avoid_cues, list) and avoid_cues, f"{key} has no avoid cues")
|
||||||
for cue in prompt_cues:
|
prompt_variant_cues = variant.get("prompt_variant_cues", [])
|
||||||
cue_text = _expect_text(f"{key}.prompt_cue", cue, 8)
|
_expect(isinstance(prompt_variant_cues, list), f"{key} prompt variant cue sets should be a list when present")
|
||||||
|
all_cue_sets = [prompt_cues, *prompt_variant_cues]
|
||||||
|
for cue_set_index, cue_set in enumerate(all_cue_sets):
|
||||||
|
_expect(isinstance(cue_set, list) and cue_set, f"{key} prompt cue set {cue_set_index} is empty")
|
||||||
|
for cue in cue_set:
|
||||||
|
cue_text = _expect_text(f"{key}.prompt_cue[{cue_set_index}]", cue, 8)
|
||||||
_expect(
|
_expect(
|
||||||
not re.search(r"\b(?:may|optionally|either|or)\b", cue_text, flags=re.IGNORECASE),
|
not re.search(r"\b(?:may|optionally|either|or)\b", cue_text, flags=re.IGNORECASE),
|
||||||
f"{key} prompt cue should be a direct model instruction, not an option list: {cue_text!r}",
|
f"{key} prompt cue should be a direct model instruction, not an option list: {cue_text!r}",
|
||||||
@@ -6846,7 +6851,17 @@ def smoke_krea2_pov_atlas_variant_prompt_routes() -> None:
|
|||||||
_expect(variant_keys == [key], f"{key} row lost exact variant metadata: {variant_keys}")
|
_expect(variant_keys == [key], f"{key} row lost exact variant metadata: {variant_keys}")
|
||||||
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore")
|
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore")
|
||||||
prompt = _expect_text(f"{key}.krea_prompt", krea.get("krea_prompt"), 80).lower()
|
prompt = _expect_text(f"{key}.krea_prompt", krea.get("krea_prompt"), 80).lower()
|
||||||
for cue in variant.get("prompt_cues") or []:
|
hard_axis_values = hard_row.get("item_axis_values") if isinstance(hard_row.get("item_axis_values"), dict) else {}
|
||||||
|
variant_indices = hard_axis_values.get("krea2_prompt_variant_indices") if isinstance(hard_axis_values, dict) else {}
|
||||||
|
selected_index = 0
|
||||||
|
if isinstance(variant_indices, dict):
|
||||||
|
try:
|
||||||
|
selected_index = int(variant_indices.get(key, 0))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
selected_index = 0
|
||||||
|
cue_sets = krea2_pose_variant_catalog.prompt_cue_sets(variant)
|
||||||
|
_expect(0 <= selected_index < len(cue_sets), f"{key} selected invalid prompt variant index {selected_index}")
|
||||||
|
for cue in cue_sets[selected_index]:
|
||||||
cue_text = _expect_text(f"{key}.prompt_cue", cue, 8).lower()
|
cue_text = _expect_text(f"{key}.prompt_cue", cue, 8).lower()
|
||||||
_expect(cue_text in prompt, f"{key} final Krea prompt lost atlas cue {cue_text!r}: {prompt}")
|
_expect(cue_text in prompt, f"{key} final Krea prompt lost atlas cue {cue_text!r}: {prompt}")
|
||||||
atlas_action_prompt = prompt.split(" camera is ", 1)[0]
|
atlas_action_prompt = prompt.split(" camera is ", 1)[0]
|
||||||
@@ -6911,6 +6926,60 @@ def smoke_krea2_pov_atlas_variant_prompt_routes() -> None:
|
|||||||
def smoke_krea2_pose_variant_catalog_policy() -> None:
|
def smoke_krea2_pose_variant_catalog_policy() -> None:
|
||||||
catalog = krea2_pose_variant_catalog.load_catalog()
|
catalog = krea2_pose_variant_catalog.load_catalog()
|
||||||
_expect(catalog.get("version") == 1, "Krea2 pose-variant loader returned wrong catalog")
|
_expect(catalog.get("version") == 1, "Krea2 pose-variant loader returned wrong catalog")
|
||||||
|
synthetic_variant = {
|
||||||
|
"key": "pov_synthetic_seeded_variant",
|
||||||
|
"prompt_cues": ["synthetic baseline atlas cue", "synthetic baseline contact anchor"],
|
||||||
|
"prompt_variant_cues": [
|
||||||
|
["synthetic alternate atlas cue", "synthetic alternate contact anchor"],
|
||||||
|
{"prompt_cues": ["synthetic second alternate cue", "synthetic second contact anchor"]},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
_expect(
|
||||||
|
krea2_pose_variant_catalog.prompt_cue_sets(synthetic_variant) == [
|
||||||
|
["synthetic baseline atlas cue", "synthetic baseline contact anchor"],
|
||||||
|
["synthetic alternate atlas cue", "synthetic alternate contact anchor"],
|
||||||
|
["synthetic second alternate cue", "synthetic second contact anchor"],
|
||||||
|
],
|
||||||
|
"Krea2 pose-variant catalog should expose baseline and optional prompt variant cue sets",
|
||||||
|
)
|
||||||
|
original_get_variant = krea2_pose_variant_catalog.get_variant
|
||||||
|
try:
|
||||||
|
def fake_get_variant(key: str, **kwargs):
|
||||||
|
if key == "pov_synthetic_seeded_variant":
|
||||||
|
return synthetic_variant
|
||||||
|
return original_get_variant(key, **kwargs)
|
||||||
|
|
||||||
|
krea2_pose_variant_catalog.get_variant = fake_get_variant
|
||||||
|
baseline_sentence = krea_pov_actions._krea2_atlas_variant_sentence(
|
||||||
|
{
|
||||||
|
"krea2_variant_keys": ["pov_synthetic_seeded_variant"],
|
||||||
|
"krea2_prompt_variant_indices": {"pov_synthetic_seeded_variant": 0},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
alternate_sentence = krea_pov_actions._krea2_atlas_variant_sentence(
|
||||||
|
{
|
||||||
|
"krea2_variant_keys": ["pov_synthetic_seeded_variant"],
|
||||||
|
"krea2_prompt_variant_indices": {"pov_synthetic_seeded_variant": 1},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
_expect("synthetic baseline atlas cue" in baseline_sentence, "Krea2 atlas sentence lost baseline prompt cue set")
|
||||||
|
_expect("synthetic alternate atlas cue" in alternate_sentence, "Krea2 atlas sentence lost selected prompt variant cue set")
|
||||||
|
selected_indices: set[int] = set()
|
||||||
|
for seed in range(4510, 4560):
|
||||||
|
axis_values = pb._axis_values_with_krea2_prompt_variant_indices(
|
||||||
|
{"krea2_variant_keys": ["pov_synthetic_seeded_variant"]},
|
||||||
|
seed_config={},
|
||||||
|
seed=seed,
|
||||||
|
row_number=1,
|
||||||
|
)
|
||||||
|
selected_indices.add(int(axis_values.get("krea2_prompt_variant_indices", {}).get("pov_synthetic_seeded_variant", 0)))
|
||||||
|
_expect(
|
||||||
|
len(selected_indices) >= 2,
|
||||||
|
f"Krea2 prompt variant selector should vary across pose seeds, got {sorted(selected_indices)}",
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
krea2_pose_variant_catalog.get_variant = original_get_variant
|
||||||
|
|
||||||
proven = krea2_pose_variant_catalog.variant_keys(status="proven")
|
proven = krea2_pose_variant_catalog.variant_keys(status="proven")
|
||||||
_expect(
|
_expect(
|
||||||
proven == [
|
proven == [
|
||||||
@@ -8570,9 +8639,35 @@ def smoke_pov_oral_position_routes() -> None:
|
|||||||
clothing_only_top_krea.get("krea_prompt"),
|
clothing_only_top_krea.get("krea_prompt"),
|
||||||
60,
|
60,
|
||||||
).lower()
|
).lower()
|
||||||
|
clothing_only_prompt_key = _clean_key(clothing_only_top_prompt)
|
||||||
|
clothing_only_state = _clean_key(clothing_only_top_pair.get("hardcore_clothing_state"))
|
||||||
|
expected_clothing_terms = [
|
||||||
|
term
|
||||||
|
for term in (
|
||||||
|
"body is fully exposed",
|
||||||
|
"bare skin unobstructed",
|
||||||
|
"pushed aside",
|
||||||
|
"partly removed",
|
||||||
|
"oral contact unobstructed",
|
||||||
|
"belt open and pants lowered below the hips",
|
||||||
|
)
|
||||||
|
if term in clothing_only_state
|
||||||
|
]
|
||||||
_expect(
|
_expect(
|
||||||
any(str(detail).lower() in clothing_only_top_prompt for detail in clothing_only_details),
|
expected_clothing_terms,
|
||||||
f"Krea2 POV Prompt Restore clothing-only final prompt did not include sampled clothing detail: {clothing_only_top_prompt}",
|
f"Krea2 POV Prompt Restore clothing-only fixture lost softcore-derived clothing state: {clothing_only_state}",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
any(term in clothing_only_prompt_key for term in expected_clothing_terms),
|
||||||
|
f"Krea2 POV Prompt Restore clothing-only final prompt did not follow softcore clothing continuity: {clothing_only_top_prompt}",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
"clothing state:" not in clothing_only_top_prompt,
|
||||||
|
f"Krea2 POV Prompt Restore clothing-only final prompt leaked raw clothing label: {clothing_only_top_prompt}",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
not any(str(detail).lower() in clothing_only_top_prompt for detail in clothing_only_details),
|
||||||
|
f"Krea2 POV Prompt Restore clothing-only final prompt should not dump raw clothing_detail: {clothing_only_top_prompt}",
|
||||||
)
|
)
|
||||||
|
|
||||||
sitting_variant_config = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPKrea2POVOralFilter"]().build(
|
sitting_variant_config = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPKrea2POVOralFilter"]().build(
|
||||||
|
|||||||
Reference in New Issue
Block a user