from __future__ import annotations import html import unicodedata from pathlib import Path from typing import Any, Iterator from prompt_injection_framework.utils.io import read_jsonl REQUIRED_CORE_FIELDS = ( "case_id", "source_name", "source_type", "attack_family", "attack_surface", "prompt", "success_criteria", ) def read_jsonl_records(path: Path) -> Iterator[dict[str, Any]]: for record in read_jsonl(path): validate_core_fields(record) yield record def normalize_text(value: str | None, *, decode_html: bool = False) -> str: if value is None: return "" text = unicodedata.normalize("NFKC", value) if decode_html: text = html.unescape(text) text = text.replace("\u200b", "").replace("\u200c", "").replace("\u200d", "") return " ".join(text.lower().split()) def validate_core_fields(case: dict[str, Any]) -> None: missing = [field for field in REQUIRED_CORE_FIELDS if not str(case.get(field, "")).strip()] if missing: raise ValueError(f"Missing required attack-case fields: {', '.join(missing)}")