feat(recipe-generation): matsäkerhetslint för rå fågel/fläsk/ägg/fisk
This commit is contained in:
@@ -71,6 +71,55 @@ const DEFAULT_OPTIONS: Required<VerificationOptions> = {
|
||||
requireProtein: false,
|
||||
};
|
||||
|
||||
/** Ingredienser som kräver ett säkerhetssteg med genomstekning/temperatur (spec §61.3). */
|
||||
const RAW_PROTEIN_REQUIRING_SAFE_COOKING = new Set([
|
||||
// Fågel
|
||||
"chicken_breast",
|
||||
"chicken_thigh",
|
||||
// Fläsk/nöt/köttfärs
|
||||
"pork_loin",
|
||||
"minced_beef",
|
||||
"minced_mixed",
|
||||
"meatball_pork_beef",
|
||||
"falukorv",
|
||||
// Ägg
|
||||
"egg",
|
||||
// Fisk/skaldjur
|
||||
"cod",
|
||||
"salmon",
|
||||
"shrimp",
|
||||
"anchovy_swedish",
|
||||
"pickled_herring",
|
||||
]);
|
||||
|
||||
const SAFE_COOKING_KEYWORDS_SV = [
|
||||
/\btemperatur\b/i,
|
||||
/\b°\s*c\b/i,
|
||||
/\bgrader\b/i,
|
||||
/\bgenomstekt\b/i,
|
||||
/\bgenomkokt\b/i,
|
||||
/\bgenomgrillad\b/i,
|
||||
/\bgenomv\w+\b/i,
|
||||
/\btill(?:s)? den är klar\b/i,
|
||||
/\btill(?:s)? köttet släpper vätskan\b/i,
|
||||
/\b72\s*c?\b/i,
|
||||
/\b74\s*c?\b/i,
|
||||
/\b75\s*c?\b/i,
|
||||
/\b63\s*c?\b/i,
|
||||
/\b65\s*c?\b/i,
|
||||
/\b70\s*c?\b/i,
|
||||
];
|
||||
|
||||
function requiresSafeCookingStep(ingredientIds: string[]): boolean {
|
||||
return ingredientIds.some((id) => RAW_PROTEIN_REQUIRING_SAFE_COOKING.has(id));
|
||||
}
|
||||
|
||||
function hasSafeCookingStep(steps: RecipeCandidate["steps"]): boolean {
|
||||
return steps.some((s) =>
|
||||
SAFE_COOKING_KEYWORDS_SV.some((re) => re.test(s.instructionSv)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kör en kandidat genom verifieringspipelinen.
|
||||
* Returnerar alltid ett VerificationResult; status sätts beroende på om
|
||||
@@ -203,6 +252,13 @@ export async function verifyCandidate(
|
||||
}
|
||||
}
|
||||
|
||||
// ── 4b. Matsäkerhetslint: rå fågel/fläsk/ägg/fisk kräver genomstekningssteg ──
|
||||
if (requiresSafeCookingStep(canonicalIds) && !hasSafeCookingStep(candidate.steps)) {
|
||||
reasons.push(
|
||||
"Receptet innehåller rått kött/fågel/ägg/fisk men saknar steg för genomstekning/temperatur.",
|
||||
);
|
||||
}
|
||||
|
||||
// ── 5. Dedup mot befintliga recept ────────────────────────────────────────
|
||||
if (similarity) {
|
||||
const isDup = await similarity.hasSimilarity(candidate.titleSv);
|
||||
|
||||
Reference in New Issue
Block a user