Shoresh Engine (Haskell, Step 5) - 12 modules: Types, Lexicon, Binyanim, Teamim, Gematria, Graph, KetivQere, Smikhut, Havdalah, Kriah, KiTov, Firmware - 33 EUnit tests, 0 failures - Firmware module verifies L1 SHA-256 hash at startup Talmudic Engine (SWI-Prolog, Step 6) - 15 modules: halt, reasoning, specification, interface - 57 PlUnit tests, 0 failures - Three cardinal halt conditions: avodah_zarah, shfichut_damim, gilui_arayot Vav Pipeline (Elixir, Steps 8-11) - 14 modules: BereishitCycle, Shema, Cloud, Manna, L1Reader, Specification, HaltConditions, ShabbatTimer, CycleLog, Chatzotzrot, ShoreshEngineClient, TalmudicEngineClient, Application - 46 ExUnit tests, 0 failures - Nishma-first architecture: hears before it speaks Sanhedrin Framework (Erlang/OTP, Step 12) - 8 modules: sanhedrin_app, sanhedrin_sup, escalation, panel_sup, panel, judge, clerk, halt_monitor - 46 EUnit tests, 0 failures (includes fix: rejected outcome now reachable) - Panel sizes: 1/3/23/71 — unanimous capital guilty → acquit (Sanhedrin 17a) - Minority opinions append-only, never deleted Korban Processor (Python, Step 13) - 6 modules: korban, shechitah, semichah, zerikah, haktarah, router Builder tooling: AGENTS.md, opencode.json, memory/, src/tools/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
1.9 KiB
Haskell
54 lines
1.9 KiB
Haskell
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
-- | Havdalah — separation and distinction.
|
|
--
|
|
-- Architecture §3.1:
|
|
-- havdalah :: Input -> [(Category, Content)]
|
|
-- "Separate an input into distinguished categories"
|
|
--
|
|
-- Havdalah is the act of making distinctions. In the processing
|
|
-- pipeline, it takes the output of vayomer (structured symbolic output)
|
|
-- and separates it into categories that can be named (kriah).
|
|
--
|
|
-- Te'amim inform the separation — the text's own divisions guide havdalah.
|
|
module Shoresh.Havdalah
|
|
( havdalah
|
|
, separateByDomain
|
|
, separateByTeamim
|
|
) where
|
|
|
|
import Shoresh.Types
|
|
import Shoresh.Teamim (ParsedVerse(..), AnnotatedWord(..), primaryDivision)
|
|
import Data.Text (Text)
|
|
import qualified Data.Text as T
|
|
import Data.Map.Strict (Map)
|
|
import qualified Data.Map.Strict as Map
|
|
|
|
-- | Separate input into distinguished categories.
|
|
-- Uses both semantic domain analysis and te'amim structure.
|
|
havdalah :: [(Shoresh, SemanticDomain)] -> [(Text, [(Shoresh, SemanticDomain)])]
|
|
havdalah items =
|
|
let grouped = Map.toList $ Map.fromListWith (++)
|
|
[ (domainName d, [(sh, d)]) | (sh, d) <- items ]
|
|
in grouped
|
|
where
|
|
domainName :: SemanticDomain -> Text
|
|
domainName d = T.pack (show d)
|
|
|
|
-- | Separate roots by their semantic domain.
|
|
separateByDomain :: [ShoreshEntry] -> Map SemanticDomain [ShoreshEntry]
|
|
separateByDomain entries =
|
|
Map.fromListWith (++) [ (sePrimaryDomain e, [e]) | e <- entries ]
|
|
|
|
-- | Separate using te'amim structure.
|
|
-- The te'amim parse tree tells us where the text itself
|
|
-- draws its divisions. Havdalah follows the text's own structure.
|
|
separateByTeamim :: ParsedVerse -> ([Text], [Text])
|
|
separateByTeamim verse =
|
|
let (left, right) = primaryDivision verse
|
|
in (collectWords left, collectWords right)
|
|
where
|
|
collectWords :: ParsedVerse -> [Text]
|
|
collectWords (Leaf w) = [awWord w]
|
|
collectWords (Branch _ l r) = collectWords l ++ collectWords r
|