From d77e7631da99e732eb5515a026a38a6ae2cf8599 Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Mon, 29 Jun 2026 04:37:27 +0200 Subject: [PATCH] Add Krea2 fingering pose candidate --- categories/krea2_pov_pose_variants.json | 37 +++++++++++++++++++++++++ docs/krea2-pov-pose-atlas.md | 8 ++++++ tools/prompt_smoke.py | 30 ++++++++++++++++++-- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/categories/krea2_pov_pose_variants.json b/categories/krea2_pov_pose_variants.json index 1a9c4bf..3f17406 100644 --- a/categories/krea2_pov_pose_variants.json +++ b/categories/krea2_pov_pose_variants.json @@ -179,6 +179,43 @@ "guide_section": "", "notes": "Small atlas family with consistent frontal sole-contact geometry; needs fixed-seed Krea2 tests before promotion to proven." } + }, + { + "key": "pov_fingering_reclined_open_thighs", + "family": "fingering", + "status": "candidate", + "atlas_folders": ["fingering"], + "action_family": "manual", + "position_keys": ["fingering", "open_thighs"], + "canonical_geometry": "First-person manual-contact view: the woman reclines or sits back with thighs spread wide toward the camera, face and torso visible behind the open legs, and the viewer hand enters from the foreground to make the visible contact between her legs.", + "prompt_cues": [ + "POV fingering position", + "woman reclines with thighs spread wide toward the camera", + "viewer hand enters from the foreground", + "fingers make the central contact between her open thighs", + "her face and torso remain visible behind the open-leg frame", + "thighs and knees form the main framing around the action" + ], + "avoid_cues": [ + "generic hand near the body without visible manual contact", + "the woman's own hand replacing the POV hand", + "mouth, foot, or penetration action competing with the foreground hand", + "closed legs hiding the contact point" + ], + "reference_images": [ + "fingering/103_fingering.png", + "fingering/69_fingering.png", + "fingering/80_fingering.png" + ], + "generator_hook": { + "module": "krea_pov_actions.py", + "route_terms": ["fingering", "finger", "manual stimulation"] + }, + "evidence": { + "fixed_seed_tests": [], + "guide_section": "", + "notes": "Atlas shows a repeated open-thigh manual-contact POV layout; needs fixed-seed Krea2 tests before promotion to proven." + } } ] } diff --git a/docs/krea2-pov-pose-atlas.md b/docs/krea2-pov-pose-atlas.md index 8a81925..a2417d8 100644 --- a/docs/krea2-pov-pose-atlas.md +++ b/docs/krea2-pov-pose-atlas.md @@ -109,3 +109,11 @@ thighs framing the lower foreground, the penis is upright near the center, and the woman's soles/toes are the contact anchor while her body and face remain behind the feet. Treat `pov_footjob_frontal_sole_stroke` as a candidate until it has fixed-seed Krea2 evidence. + +### Fingering + +The fingering folder repeats a first-person manual-contact layout: the woman is +reclined or sitting back with thighs spread wide toward camera, her face and +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. diff --git a/tools/prompt_smoke.py b/tools/prompt_smoke.py index 2b67641..a248483 100644 --- a/tools/prompt_smoke.py +++ b/tools/prompt_smoke.py @@ -6792,6 +6792,11 @@ def smoke_krea2_pose_variant_catalog_policy() -> None: ], f"Krea2 pose-variant outercourse filtering changed unexpectedly: {outercourse}", ) + manual = krea2_pose_variant_catalog.variant_keys(action_family="manual") + _expect( + manual == ["pov_fingering_reclined_open_thighs"], + f"Krea2 pose-variant manual filtering changed unexpectedly: {manual}", + ) handjob = krea2_pose_variant_catalog.get_variant("pov_handjob_upright_centered") _expect( any("woman's right hand wraps" in str(cue) for cue in handjob.get("prompt_cues", [])), @@ -6806,6 +6811,12 @@ def smoke_krea2_pose_variant_catalog_policy() -> None: any("both soles press" in str(cue) for cue in footjob.get("prompt_cues", [])), "Footjob variant lost sole-contact cue", ) + fingering = krea2_pose_variant_catalog.get_variant("pov_fingering_reclined_open_thighs") + _expect(fingering.get("status") == "candidate", "Fingering variant should remain a candidate until fixed-seed evidence exists") + _expect( + any("viewer hand enters from the foreground" in str(cue) for cue in fingering.get("prompt_cues", [])), + "Fingering variant lost foreground-hand cue", + ) refs = krea2_pose_variant_catalog.reference_paths("pov_boobjob_upright_cleavage") _expect(refs and all(path.name.endswith(".png") for path in refs), "Boobjob reference paths are not image paths") _expect(all("bg" not in str(path).lower() for path in refs), "Reference paths should not include background-only atlas images") @@ -6866,19 +6877,24 @@ def smoke_krea2_tuning_report_policy() -> None: footjob = by_key.get("pov_footjob_frontal_sole_stroke") or {} _expect(footjob.get("coverage_state") == "needs_fixed_seed_tests", "Footjob report should need fixed-seed tests") _expect(footjob.get("accepted_evidence_count") == 0, "Footjob report should not have accepted evidence yet") + 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") 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") == 2, "Krea2 tuning report candidate count changed") + _expect(summary.get("status_counts", {}).get("candidate") == 3, "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", ], f"Krea2 tuning report missing-evidence set changed: {summary.get('variants_without_accepted_evidence')}", ) plans = krea2_tuning_report.next_test_plans() _expect( - [plan.get("key") for plan in plans] == ["pov_ballsucking_low_head", "pov_footjob_frontal_sole_stroke"], + [plan.get("key") for plan in plans] + == ["pov_ballsucking_low_head", "pov_footjob_frontal_sole_stroke", "pov_fingering_reclined_open_thighs"], "Krea2 tuning report next plans changed", ) plan_by_key = {plan.get("key"): plan for plan in plans} @@ -6904,6 +6920,15 @@ def smoke_krea2_tuning_report_policy() -> None: any(str(path).endswith("footjob/59_footjob.png") for path in footjob_plan.get("reference_paths") or []), "Footjob test plan lost atlas reference path", ) + fingering_plan = plan_by_key["pov_fingering_reclined_open_thighs"] + _expect( + "viewer hand enters from the foreground" in " ".join(fingering_plan.get("prompt_cues") or []), + "Fingering test plan lost foreground-hand cue", + ) + _expect( + any(str(path).endswith("fingering/103_fingering.png") for path in fingering_plan.get("reference_paths") or []), + "Fingering test plan lost atlas reference path", + ) with tempfile.TemporaryDirectory() as tmpdir: atlas_root = Path(tmpdir) for folder in ("doggy", "doggy_control", "custom_pose", "custom_pose_control", "bg", "woman", "doggy_bg"): @@ -6937,6 +6962,7 @@ def smoke_krea2_tuning_report_policy() -> None: 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("needs_fixed_seed_tests" in markdown, "Krea2 tuning report markdown lost coverage state") _expect("Prompt cues" in markdown, "Krea2 tuning report markdown lost next-test cue section") _expect("Avoid cues" in markdown, "Krea2 tuning report markdown lost next-test avoid section")