diff --git a/route_metadata.py b/route_metadata.py index 787130d..15a2302 100644 --- a/route_metadata.py +++ b/route_metadata.py @@ -16,13 +16,29 @@ except ImportError: # Allows local smoke tests from the repository root. def row_action_family(row: Any, default: str = "") -> str: if not isinstance(row, dict): return default - return normalize_hardcore_action_family(row.get("action_family"), default) + family = normalize_hardcore_action_family(row.get("action_family"), "") + if family: + return family + metadata = row.get("item_template_metadata") + if isinstance(metadata, dict): + family = template_metadata_policy.template_action_family(metadata) + if family: + return family + return default def row_position_family(row: Any, default: str = "") -> str: if not isinstance(row, dict): return default - return normalize_hardcore_position_family(str(row.get("position_family") or "").strip().lower(), default) + family = normalize_hardcore_position_family(str(row.get("position_family") or "").strip().lower(), "") + if family: + return family + metadata = row.get("item_template_metadata") + if isinstance(metadata, dict): + family = template_metadata_policy.template_position_family(metadata) + if family: + return family + return default def _raw_position_key_values(row: dict[str, Any]) -> list[Any]: @@ -49,6 +65,11 @@ def row_position_keys(row: Any, *, include_unknown: bool = False) -> list[str]: return [] values = _raw_position_key_values(row) selected = normalize_hardcore_position_values(values) + metadata = row.get("item_template_metadata") + if isinstance(metadata, dict): + for key in template_metadata_policy.template_position_keys(metadata): + if key and key not in selected: + selected.append(key) if not include_unknown: return selected for value in values: @@ -59,4 +80,12 @@ def row_position_keys(row: Any, *, include_unknown: bool = False) -> list[str]: def row_formatter_hints(row: Any, route: str) -> list[str]: - return template_metadata_policy.formatter_hints_for_route(row, route) + hints: list[str] = [] + for hint in template_metadata_policy.formatter_hints_for_route(row, route): + if hint not in hints: + hints.append(hint) + if isinstance(row, dict) and isinstance(row.get("item_template_metadata"), dict): + for hint in template_metadata_policy.formatter_hints_for_route(row["item_template_metadata"], route): + if hint not in hints: + hints.append(hint) + return hints diff --git a/tools/prompt_smoke.py b/tools/prompt_smoke.py index 182944b..9f9d924 100644 --- a/tools/prompt_smoke.py +++ b/tools/prompt_smoke.py @@ -3864,6 +3864,46 @@ def smoke_hardcore_position_config_policy() -> None: route_metadata.row_formatter_hints(route_row, "caption") == ["shared formatter cue", "caption formatter cue"], "Route metadata formatter hint routing changed", ) + nested_route_row = { + "item_template_metadata": { + "action_family": "oral", + "position_family": "oral", + "position_keys": ["kneeling", "open_thighs"], + "formatter_hint": {"krea2": "nested krea cue", "sdxl": "nested sdxl cue", "training_caption": "nested caption cue"}, + } + } + _expect( + route_metadata.row_action_family(nested_route_row) == "oral", + "Route metadata should fall back to nested template action family", + ) + _expect( + route_metadata.row_position_family(nested_route_row) == "oral", + "Route metadata should fall back to nested template position family", + ) + _expect( + route_metadata.row_position_keys(nested_route_row) == ["kneeling", "open_thighs"], + "Route metadata should fall back to nested template position keys", + ) + _expect( + route_metadata.row_formatter_hints(nested_route_row, "krea") == ["nested krea cue"], + "Route metadata should fall back to nested Krea formatter hints", + ) + merged_route_row = { + "position_key": "standing", + "formatter_hints": {"all": ["shared cue"]}, + "item_template_metadata": { + "position_keys": ["kneeling"], + "formatter_hint": {"caption": "nested caption cue"}, + }, + } + _expect( + route_metadata.row_position_keys(merged_route_row) == ["standing", "kneeling"], + "Route metadata should merge top-level and nested position keys", + ) + _expect( + route_metadata.row_formatter_hints(merged_route_row, "caption") == ["shared cue", "nested caption cue"], + "Route metadata should merge top-level and nested formatter hints", + ) route_hints = category_template_metadata.formatter_hints_for_route( {"formatter_hints": {"all": ["shared formatter cue"], "krea2": ["krea formatter cue"]}}, "krea2",