Validate pair content seed rerolls
This commit is contained in:
@@ -27,7 +27,8 @@ The map audit currently sees:
|
|||||||
every registered action and position family except documented special cases
|
every registered action and position family except documented special cases
|
||||||
covered by dedicated smoke fixtures.
|
covered by dedicated smoke fixtures.
|
||||||
- Pair seed simulation, so Insta/OF soft/hard metadata and formatter outputs
|
- Pair seed simulation, so Insta/OF soft/hard metadata and formatter outputs
|
||||||
prove locked determinism and pose-only reroll behavior.
|
prove locked determinism, content-only reroll behavior, and pose-only reroll
|
||||||
|
behavior.
|
||||||
|
|
||||||
## Architectural Finding
|
## Architectural Finding
|
||||||
|
|
||||||
@@ -646,7 +647,8 @@ Near-term:
|
|||||||
- Keep same-room pair continuity synchronized in both assembled prompt text and
|
- Keep same-room pair continuity synchronized in both assembled prompt text and
|
||||||
`hardcore_row.scene_text`; `tools/prompt_smoke.py` covers this drift case.
|
`hardcore_row.scene_text`; `tools/prompt_smoke.py` covers this drift case.
|
||||||
- Keep pair seed behavior synchronized across soft/hard rows; the route
|
- Keep pair seed behavior synchronized across soft/hard rows; the route
|
||||||
simulator now checks locked pair determinism and pose-only hard-action rerolls.
|
simulator now checks locked pair determinism, content-only soft outfit
|
||||||
|
rerolls, and pose-only hard-action rerolls.
|
||||||
|
|
||||||
Medium-term:
|
Medium-term:
|
||||||
|
|
||||||
|
|||||||
@@ -1006,6 +1006,8 @@ issues for:
|
|||||||
- route-family coverage for registered action and position families, excluding
|
- route-family coverage for registered action and position families, excluding
|
||||||
only documented special cases that have their own smoke fixtures;
|
only documented special cases that have their own smoke fixtures;
|
||||||
- pair seed determinism for Insta/OF metadata and formatted soft/hard outputs;
|
- pair seed determinism for Insta/OF metadata and formatted soft/hard outputs;
|
||||||
|
- pair content rerolls changing soft outfit/teaser content while keeping cast,
|
||||||
|
scene, hard action, and composition axes stable;
|
||||||
- pair pose rerolls changing hardcore action metadata while keeping cast,
|
- pair pose rerolls changing hardcore action metadata while keeping cast,
|
||||||
scene, soft outfit, and composition axes stable;
|
scene, soft outfit, and composition axes stable;
|
||||||
- pose-axis rerolls changing cast/scene metadata or failing to move pose/action
|
- pose-axis rerolls changing cast/scene metadata or failing to move pose/action
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ AUDIT_DOC_SNIPPETS: tuple[tuple[str, str], ...] = (
|
|||||||
"docs/prompt-pool-routing-map.md",
|
"docs/prompt-pool-routing-map.md",
|
||||||
"pair seed determinism for Insta/OF metadata",
|
"pair seed determinism for Insta/OF metadata",
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"docs/prompt-pool-routing-map.md",
|
||||||
|
"pair content rerolls changing soft outfit/teaser content",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"docs/prompt-pool-routing-map.md",
|
"docs/prompt-pool-routing-map.md",
|
||||||
"pair pose rerolls changing hardcore action metadata",
|
"pair pose rerolls changing hardcore action metadata",
|
||||||
|
|||||||
@@ -936,6 +936,7 @@ def _pair_seed_snapshot(pair: dict[str, Any]) -> dict[str, Any]:
|
|||||||
"soft_scene_text": soft_row.get("scene_text"),
|
"soft_scene_text": soft_row.get("scene_text"),
|
||||||
"hard_scene_text": hard_row.get("scene_text"),
|
"hard_scene_text": hard_row.get("scene_text"),
|
||||||
"soft_item": soft_row.get("item"),
|
"soft_item": soft_row.get("item"),
|
||||||
|
"soft_pose": soft_row.get("pose"),
|
||||||
"hard_item": hard_row.get("item"),
|
"hard_item": hard_row.get("item"),
|
||||||
"hard_position_key": hard_row.get("position_key"),
|
"hard_position_key": hard_row.get("position_key"),
|
||||||
"hard_position_keys": hard_row.get("position_keys") or [],
|
"hard_position_keys": hard_row.get("position_keys") or [],
|
||||||
@@ -1105,6 +1106,53 @@ def _pair_seed_pose_reroll_check(seed: int) -> dict[str, Any]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _pair_seed_content_reroll_check(seed: int) -> dict[str, Any]:
|
||||||
|
name = "pair_seed.content_reroll"
|
||||||
|
base = _pair_seed_probe(seed)
|
||||||
|
base_snapshot = _pair_seed_snapshot(base)
|
||||||
|
changed = False
|
||||||
|
changed_seed = None
|
||||||
|
changed_field_names: list[str] = []
|
||||||
|
issues: list[str] = []
|
||||||
|
stable_fields = (
|
||||||
|
"shared_cast_descriptors",
|
||||||
|
"soft_cast_descriptor_text",
|
||||||
|
"hard_cast_descriptor_text",
|
||||||
|
"soft_scene_text",
|
||||||
|
"hard_scene_text",
|
||||||
|
"hard_item",
|
||||||
|
"hard_position_key",
|
||||||
|
"hard_source_role_graph",
|
||||||
|
"soft_composition",
|
||||||
|
"hard_composition",
|
||||||
|
)
|
||||||
|
changed_fields = ("soft_item", "soft_pose")
|
||||||
|
for reroll_seed in range(seed + 1, seed + 16):
|
||||||
|
rerolled = _pair_seed_probe(seed, reroll_axis="content", reroll_seed=reroll_seed)
|
||||||
|
rerolled_snapshot = _pair_seed_snapshot(rerolled)
|
||||||
|
field_issues = _same_fields_issues(name, base_snapshot, rerolled_snapshot, stable_fields, reroll_seed)
|
||||||
|
if field_issues:
|
||||||
|
issues.extend(field_issues)
|
||||||
|
break
|
||||||
|
changed_field_names = [
|
||||||
|
field for field in changed_fields if base_snapshot.get(field) != rerolled_snapshot.get(field)
|
||||||
|
]
|
||||||
|
if changed_field_names:
|
||||||
|
changed = True
|
||||||
|
changed_seed = reroll_seed
|
||||||
|
break
|
||||||
|
if not changed:
|
||||||
|
issues.append("pair content reroll did not change soft_item or soft_pose within 15 attempts")
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"base": _row_summary(base.get("softcore_row") or {}),
|
||||||
|
"changed": changed,
|
||||||
|
"changed_seed": changed_seed,
|
||||||
|
"changed_fields": changed_field_names,
|
||||||
|
"issues": issues,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _seed_axis_checks(seed: int) -> list[dict[str, Any]]:
|
def _seed_axis_checks(seed: int) -> list[dict[str, Any]]:
|
||||||
return [
|
return [
|
||||||
_seed_determinism_check(seed),
|
_seed_determinism_check(seed),
|
||||||
@@ -1144,6 +1192,7 @@ def _seed_axis_checks(seed: int) -> list[dict[str, Any]]:
|
|||||||
def _pair_seed_checks(seed: int) -> list[dict[str, Any]]:
|
def _pair_seed_checks(seed: int) -> list[dict[str, Any]]:
|
||||||
return [
|
return [
|
||||||
_pair_seed_determinism_check(seed),
|
_pair_seed_determinism_check(seed),
|
||||||
|
_pair_seed_content_reroll_check(seed),
|
||||||
_pair_seed_pose_reroll_check(seed),
|
_pair_seed_pose_reroll_check(seed),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -7918,7 +7918,7 @@ def smoke_prompt_route_simulation_policy() -> None:
|
|||||||
_expect(summary.get("cases") == 14, "Prompt route simulation case count changed unexpectedly")
|
_expect(summary.get("cases") == 14, "Prompt route simulation case count changed unexpectedly")
|
||||||
_expect(summary.get("coverage_checks") == 2, "Prompt route simulation lost family coverage checks")
|
_expect(summary.get("coverage_checks") == 2, "Prompt route simulation lost family coverage checks")
|
||||||
_expect(summary.get("axis_checks") == 6, "Prompt route simulation lost axis check coverage")
|
_expect(summary.get("axis_checks") == 6, "Prompt route simulation lost axis check coverage")
|
||||||
_expect(summary.get("pair_seed_checks") == 2, "Prompt route simulation lost pair seed check coverage")
|
_expect(summary.get("pair_seed_checks") == 3, "Prompt route simulation lost pair seed check coverage")
|
||||||
_expect(summary.get("issues") == 0, f"Prompt route simulation reported issues: {report.get('issues')}")
|
_expect(summary.get("issues") == 0, f"Prompt route simulation reported issues: {report.get('issues')}")
|
||||||
cases = {case.get("name"): case for case in report.get("cases") or []}
|
cases = {case.get("name"): case for case in report.get("cases") or []}
|
||||||
for route_name in (
|
for route_name in (
|
||||||
@@ -7981,7 +7981,7 @@ def smoke_prompt_route_simulation_policy() -> None:
|
|||||||
):
|
):
|
||||||
_expect(axis_checks[check_name].get("changed") is True, f"{check_name} should prove its axis can reroll")
|
_expect(axis_checks[check_name].get("changed") is True, f"{check_name} should prove its axis can reroll")
|
||||||
pair_seed_checks = {check.get("name"): check for check in report.get("pair_seed_checks") or []}
|
pair_seed_checks = {check.get("name"): check for check in report.get("pair_seed_checks") or []}
|
||||||
for check_name in ("pair_seed.locked_determinism", "pair_seed.pose_reroll"):
|
for check_name in ("pair_seed.locked_determinism", "pair_seed.content_reroll", "pair_seed.pose_reroll"):
|
||||||
check = pair_seed_checks.get(check_name) or {}
|
check = pair_seed_checks.get(check_name) or {}
|
||||||
_expect(check, f"Prompt route simulation lost pair seed check {check_name}")
|
_expect(check, f"Prompt route simulation lost pair seed check {check_name}")
|
||||||
_expect(not check.get("issues"), f"Prompt route simulation pair seed check reported issues: {check_name}")
|
_expect(not check.get("issues"), f"Prompt route simulation pair seed check reported issues: {check_name}")
|
||||||
@@ -7989,6 +7989,10 @@ def smoke_prompt_route_simulation_policy() -> None:
|
|||||||
pair_seed_checks["pair_seed.locked_determinism"].get("changed") is False,
|
pair_seed_checks["pair_seed.locked_determinism"].get("changed") is False,
|
||||||
"Pair locked determinism check should not be a reroll",
|
"Pair locked determinism check should not be a reroll",
|
||||||
)
|
)
|
||||||
|
_expect(
|
||||||
|
pair_seed_checks["pair_seed.content_reroll"].get("changed") is True,
|
||||||
|
"Pair content reroll should prove soft outfit/content can reroll while hard action stays locked",
|
||||||
|
)
|
||||||
_expect(
|
_expect(
|
||||||
pair_seed_checks["pair_seed.pose_reroll"].get("changed") is True,
|
pair_seed_checks["pair_seed.pose_reroll"].get("changed") is True,
|
||||||
"Pair pose reroll should prove hard action can reroll while soft/cast/scene axes stay locked",
|
"Pair pose reroll should prove hard action can reroll while soft/cast/scene axes stay locked",
|
||||||
|
|||||||
Reference in New Issue
Block a user