Files
bikoret/shoresh-engine/src/Shoresh/Havdalah.hs
T
Scott KarpandClaude Sonnet 4.6 80ec364da6 Phase 1-2 build: Steps 5-6, 8-13
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>
2026-02-26 14:02:34 -05:00

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