Add Krea2 wand atlas candidate

This commit is contained in:
2026-06-29 07:44:03 +02:00
parent 05f14cecc7
commit e028419e6d
4 changed files with 97 additions and 6 deletions
+38
View File
@@ -217,6 +217,44 @@
"notes": "Atlas shows a repeated open-thigh manual-contact POV layout; needs fixed-seed Krea2 tests before promotion to proven."
}
},
{
"key": "pov_wand_foreground_tool_contact",
"family": "wand",
"status": "candidate",
"atlas_folders": ["wand"],
"action_family": "toy",
"position_keys": ["wand", "toy_contact", "open_thighs"],
"canonical_geometry": "First-person toy-contact view: the woman reclines or sits back with thighs spread toward the camera, face and torso visible behind the open-leg frame, and the viewer hand holds a wand-style toy from the foreground with the rounded head pressed to the central contact point.",
"prompt_cues": [
"POV wand toy position",
"woman reclines with thighs spread wide toward the camera",
"viewer hand holds a wand-style toy from the foreground",
"rounded toy head is pressed to the central contact point between her open thighs",
"her face and torso remain visible behind the open-leg frame",
"thighs and knees form the main frame around the foreground tool"
],
"avoid_cues": [
"generic toy nearby without contact",
"the woman holding the toy when the foreground viewer hand is intended",
"mouth, foot, or penetration action competing with the toy contact",
"closed legs hiding the contact point",
"toy floating without a visible hand or handle"
],
"reference_images": [
"wand/106_wand_.png",
"wand/107_wand_.png",
"wand/108_wand_.png"
],
"generator_hook": {
"module": "krea_pov_actions.py",
"route_terms": ["wand", "toy", "vibrator"]
},
"evidence": {
"fixed_seed_tests": [],
"guide_section": "",
"notes": "The wand folder repeats a foreground-hand toy-contact layout with open thighs and the visible partner behind the tool; needs fixed-seed Krea2 tests before promotion to proven."
}
},
{
"key": "pov_spread_open_thigh_presentation",
"family": "spread",
+15
View File
@@ -28,6 +28,11 @@ catalog variants are proven or pending and which atlas pose folders are still
unmapped by the catalog. Unmapped folders include sample pose/control image
paths and a suggested candidate key to start the next catalog entry.
The `ready` folder name is misleading for prompt planning: treat it as an
aftermath/open-thigh family with visible fluid at the central contact area, not
as a neutral setup pose. The report therefore suggests an aftermath candidate
key for that folder until a proper catalog variant is added.
## Inventory
| Family | Pose images | Control images | First sample |
@@ -118,6 +123,16 @@ torso visible behind the open-leg frame, and the viewer hand entering from the
foreground as the contact anchor. Treat `pov_fingering_reclined_open_thighs` as
a candidate until it has fixed-seed Krea2 evidence.
### Wand / Toy Contact
The wand folder repeats a close first-person tool-contact layout: the woman is
reclined or sitting back with thighs spread toward camera, face and torso visible
behind the open-leg frame, and the viewer hand holding a wand-style toy from the
foreground with the rounded head pressed to the central contact point. Treat
`pov_wand_foreground_tool_contact` as a candidate until it has fixed-seed Krea2
evidence. Keep the visible hand/handle in the wording; otherwise Krea2 may float
the toy or transfer ownership to the visible partner.
### Spread / Open-Thigh Presentation
The spread folder is a setup/presentation family rather than a required contact
+2
View File
@@ -144,6 +144,8 @@ def atlas_coverage_summary(atlas_root: str | Path | None = None) -> dict[str, An
def _suggested_variant_key(folder_name: str) -> str:
if folder_name.lower() == "ready":
return "pov_ejaculation_aftermath_open_thigh_candidate"
normalized = "".join(char if char.isalnum() else "_" for char in folder_name.lower()).strip("_")
while "__" in normalized:
normalized = normalized.replace("__", "_")
+42 -6
View File
@@ -6810,6 +6810,11 @@ def smoke_krea2_pose_variant_catalog_policy() -> None:
manual == ["pov_fingering_reclined_open_thighs"],
f"Krea2 pose-variant manual filtering changed unexpectedly: {manual}",
)
toy = krea2_pose_variant_catalog.variant_keys(action_family="toy")
_expect(
toy == ["pov_wand_foreground_tool_contact"],
f"Krea2 pose-variant toy filtering changed unexpectedly: {toy}",
)
interaction = krea2_pose_variant_catalog.variant_keys(action_family="interaction")
_expect(
interaction == ["pov_spread_open_thigh_presentation"],
@@ -6845,6 +6850,12 @@ def smoke_krea2_pose_variant_catalog_policy() -> None:
any("viewer hand enters from the foreground" in str(cue) for cue in fingering.get("prompt_cues", [])),
"Fingering variant lost foreground-hand cue",
)
wand = krea2_pose_variant_catalog.get_variant("pov_wand_foreground_tool_contact")
_expect(wand.get("status") == "candidate", "Wand variant should remain a candidate until fixed-seed evidence exists")
_expect(
any("viewer hand holds a wand-style toy from the foreground" in str(cue) for cue in wand.get("prompt_cues", [])),
"Wand variant lost foreground tool-hold cue",
)
spread = krea2_pose_variant_catalog.get_variant("pov_spread_open_thigh_presentation")
_expect(spread.get("status") == "candidate", "Spread variant should remain a candidate until fixed-seed evidence exists")
_expect(
@@ -6974,6 +6985,9 @@ def smoke_krea2_tuning_report_policy() -> None:
fingering = by_key.get("pov_fingering_reclined_open_thighs") or {}
_expect(fingering.get("coverage_state") == "needs_fixed_seed_tests", "Fingering report should need fixed-seed tests")
_expect(fingering.get("accepted_evidence_count") == 0, "Fingering report should not have accepted evidence yet")
wand = by_key.get("pov_wand_foreground_tool_contact") or {}
_expect(wand.get("coverage_state") == "needs_fixed_seed_tests", "Wand report should need fixed-seed tests")
_expect(wand.get("accepted_evidence_count") == 0, "Wand report should not have accepted evidence yet")
spread = by_key.get("pov_spread_open_thigh_presentation") or {}
_expect(spread.get("coverage_state") == "needs_fixed_seed_tests", "Spread report should need fixed-seed tests")
_expect(spread.get("accepted_evidence_count") == 0, "Spread report should not have accepted evidence yet")
@@ -7009,12 +7023,13 @@ def smoke_krea2_tuning_report_policy() -> None:
_expect(reverse_cowgirl_alt.get("accepted_evidence_count") == 0, "Reverse cowgirl alt report should not have accepted evidence yet")
summary = krea2_tuning_report.coverage_summary()
_expect(summary.get("status_counts", {}).get("proven") == 3, "Krea2 tuning report proven count changed")
_expect(summary.get("status_counts", {}).get("candidate") == 14, "Krea2 tuning report candidate count changed")
_expect(summary.get("status_counts", {}).get("candidate") == 15, "Krea2 tuning report candidate count changed")
_expect(
summary.get("variants_without_accepted_evidence") == [
"pov_ballsucking_low_head",
"pov_footjob_frontal_sole_stroke",
"pov_fingering_reclined_open_thighs",
"pov_wand_foreground_tool_contact",
"pov_spread_open_thigh_presentation",
"pov_blowjob_top_down_vertical_shaft",
"pov_blowjob_side_profile_oral",
@@ -7036,6 +7051,7 @@ def smoke_krea2_tuning_report_policy() -> None:
"pov_ballsucking_low_head",
"pov_footjob_frontal_sole_stroke",
"pov_fingering_reclined_open_thighs",
"pov_wand_foreground_tool_contact",
"pov_spread_open_thigh_presentation",
"pov_blowjob_top_down_vertical_shaft",
"pov_blowjob_side_profile_oral",
@@ -7082,6 +7098,15 @@ def smoke_krea2_tuning_report_policy() -> None:
any(str(path).endswith("fingering/103_fingering.png") for path in fingering_plan.get("reference_paths") or []),
"Fingering test plan lost atlas reference path",
)
wand_plan = plan_by_key["pov_wand_foreground_tool_contact"]
_expect(
"viewer hand holds a wand-style toy from the foreground" in " ".join(wand_plan.get("prompt_cues") or []),
"Wand test plan lost foreground tool-hold cue",
)
_expect(
any(str(path).endswith("wand/106_wand_.png") for path in wand_plan.get("reference_paths") or []),
"Wand test plan lost atlas reference path",
)
spread_plan = plan_by_key["pov_spread_open_thigh_presentation"]
_expect(
"legs raised or knees held wide" in " ".join(spread_plan.get("prompt_cues") or []),
@@ -7183,38 +7208,49 @@ def smoke_krea2_tuning_report_policy() -> None:
)
with tempfile.TemporaryDirectory() as tmpdir:
atlas_root = Path(tmpdir)
for folder in ("doggy", "doggy_control", "custom_pose", "custom_pose_control", "bg", "woman", "doggy_bg"):
for folder in ("doggy", "doggy_control", "custom_pose", "custom_pose_control", "ready", "ready_control", "bg", "woman", "doggy_bg"):
folder_path = atlas_root / folder
folder_path.mkdir()
(folder_path / f"{folder}_sample.png").write_bytes(b"")
(atlas_root / "custom_pose" / "custom_pose_b.png").write_bytes(b"")
(atlas_root / "custom_pose_control" / "custom_pose_control_b.png").write_bytes(b"")
(atlas_root / "ready" / "ready_b.png").write_bytes(b"")
(atlas_root / "ready_control" / "ready_control_b.png").write_bytes(b"")
atlas_rows = krea2_tuning_report.atlas_folder_rows(atlas_root=atlas_root)
atlas_by_folder = {row.get("folder"): row for row in atlas_rows}
_expect(atlas_by_folder.get("doggy", {}).get("mapped") is True, "Atlas report should mark catalog folders as mapped")
_expect(atlas_by_folder.get("custom_pose", {}).get("mapped") is False, "Atlas report should expose unmapped pose folders")
_expect(atlas_by_folder.get("ready", {}).get("mapped") is False, "Atlas report should expose unmapped ready folder")
_expect("doggy_control" not in atlas_by_folder, "Atlas report should exclude control folders")
_expect("doggy_bg" not in atlas_by_folder, "Atlas report should exclude background folders")
_expect("bg" not in atlas_by_folder, "Atlas report should exclude shared bg folder")
_expect("woman" not in atlas_by_folder, "Atlas report should exclude non-pose woman folder")
atlas_summary = krea2_tuning_report.atlas_coverage_summary(atlas_root=atlas_root)
_expect(atlas_summary.get("pose_folder_count") == 2, "Atlas report should count only pose folders")
_expect(atlas_summary.get("pose_folder_count") == 3, "Atlas report should count only pose folders")
_expect(atlas_summary.get("mapped_folder_count") == 1, "Atlas report should count mapped pose folders")
_expect(atlas_summary.get("unmapped_folders") == ["custom_pose"], "Atlas report should identify unmapped pose folders")
_expect(atlas_summary.get("unmapped_folders") == ["custom_pose", "ready"], "Atlas report should identify unmapped pose folders")
gap_plans = krea2_tuning_report.atlas_gap_plans(atlas_root=atlas_root, sample_limit=2)
_expect([plan.get("folder") for plan in gap_plans] == ["custom_pose"], "Atlas gap plans should follow unmapped folders")
custom_gap = gap_plans[0]
_expect([plan.get("folder") for plan in gap_plans] == ["custom_pose", "ready"], "Atlas gap plans should follow unmapped folders")
gap_by_folder = {plan.get("folder"): plan for plan in gap_plans}
custom_gap = gap_by_folder["custom_pose"]
_expect(custom_gap.get("suggested_variant_key") == "pov_custom_pose_candidate", "Atlas gap plan should suggest stable variant key")
_expect(len(custom_gap.get("sample_images") or []) == 2, "Atlas gap plan should include deterministic sample images")
_expect(len(custom_gap.get("control_images") or []) == 2, "Atlas gap plan should include deterministic control images")
ready_gap = gap_by_folder["ready"]
_expect(
ready_gap.get("suggested_variant_key") == "pov_ejaculation_aftermath_open_thigh_candidate",
"Atlas gap plan should not treat ready as a neutral setup pose",
)
atlas_markdown = krea2_tuning_report.markdown_report(atlas_root=atlas_root)
_expect("Atlas Folder Coverage" in atlas_markdown, "Krea2 tuning report markdown lost atlas coverage section")
_expect("custom_pose" in atlas_markdown, "Krea2 tuning report markdown lost unmapped atlas folder")
_expect("pov_custom_pose_candidate" in atlas_markdown, "Krea2 tuning report markdown lost suggested gap key")
_expect("pov_ejaculation_aftermath_open_thigh_candidate" in atlas_markdown, "Krea2 tuning report markdown lost ready aftermath suggested key")
markdown = krea2_tuning_report.markdown_report()
_expect("pov_ballsucking_low_head" in markdown, "Krea2 tuning report markdown lost candidate variant")
_expect("pov_footjob_frontal_sole_stroke" in markdown, "Krea2 tuning report markdown lost footjob candidate variant")
_expect("pov_fingering_reclined_open_thighs" in markdown, "Krea2 tuning report markdown lost fingering candidate variant")
_expect("pov_wand_foreground_tool_contact" in markdown, "Krea2 tuning report markdown lost wand candidate variant")
_expect("pov_spread_open_thigh_presentation" in markdown, "Krea2 tuning report markdown lost spread candidate variant")
_expect("pov_blowjob_top_down_vertical_shaft" in markdown, "Krea2 tuning report markdown lost blowjob top-view candidate variant")
_expect("pov_blowjob_side_profile_oral" in markdown, "Krea2 tuning report markdown lost blowjob side candidate variant")