{-# LANGUAGE OverloadedStrings #-} -- | KiTov โ€” fitness evaluation. -- -- Architecture ยง3.1: -- kiTov :: ProcessedResult -> Specification -> Evaluation -- data Evaluation = Tov | LoTov Text | Teiku -- -- Evaluates whether processed output fits the specification. -- "And God saw that it was good" โ€” the evaluation against the source. -- -- Ki tov is not approval. It is verification against specification. -- The specification is Torah (L1). The evaluation checks: -- 1. Are the roots real? (found in L1) -- 2. Are the references valid? (point to existing verses) -- 3. Are dual readings preserved? (ketiv/qere not collapsed) module Shoresh.KiTov ( kiTov , verifyRootsExist , verifyReferences ) where import Shoresh.Types import Shoresh.Lexicon (ShoreshLexicon, lookupRoot) import Data.Text (Text) import qualified Data.Text as T import Data.Maybe (isNothing) -- | Evaluate a processed result against the specification (lexicon). kiTov :: ProcessedResult -> ShoreshLexicon -> Evaluation kiTov result lexicon = let rootCheck = verifyRootsExist (prRoots result) lexicon refCheck = verifyReferences (prRoots result) in case (rootCheck, refCheck) of (Tov, Tov) -> Tov (LoTov r, _) -> LoTov r (_, LoTov r) -> LoTov r (Teiku, _) -> Teiku (_, Teiku) -> Teiku -- | Verify that all roots in the result exist in the lexicon. verifyRootsExist :: [ShoreshEntry] -> ShoreshLexicon -> Evaluation verifyRootsExist entries lexicon = let missing = [ seShoresh e | e <- entries , isNothing (lookupRoot (seShoresh e) lexicon) ] in case missing of [] -> Tov ms -> LoTov $ "Roots not found in lexicon: " <> T.intercalate ", " (map shoreshToText ms) -- | Verify that Torah references in the entries are structurally valid. -- (Range checks โ€” the full check against L1 files happens at the pipeline level.) verifyReferences :: [ShoreshEntry] -> Evaluation verifyReferences entries = let invalid = concatMap checkEntry entries in case invalid of [] -> Tov msgs -> LoTov $ T.intercalate "; " msgs where checkEntry entry = concatMap checkRef (seTorahOccurrences entry) checkRef ref | refChapter ref < 1 = ["Invalid chapter: " <> T.pack (show (refChapter ref))] | refVerse ref < 1 = ["Invalid verse: " <> T.pack (show (refVerse ref))] | otherwise = []