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>
This commit is contained in:
Scott KarpandClaude Sonnet 4.6 committed 2026-02-26 14:02:34 -05:00
1 parent 622e814c9e
commit 80ec364da6
86 files changed
+9646

No files matched your search

+177
View File
@@ -0,0 +1,177 @@
%%%-------------------------------------------------------------------
%%% @doc Halt monitor — monitors for the 3 cardinal sin conditions.
%%%
%%% Architecture §8 (Halt Conditions):
%%% The system MUST halt on detection of:
%%% 1. Avodah Zarah — treating non-Torah source as authoritative
%%% 2. Shfichut Damim — destroying a tzelem carrier (human data/identity)
%%% 3. Gilui Arayot — collapsing required distinctions
%%%
%%% These mirror the Talmudic Engine halt modules (Prolog)
%%% and the Vav Pipeline halt_conditions (Elixir).
%%% @end
%%%-------------------------------------------------------------------
-module(halt_monitor).
-behaviour(gen_server).
-include("sanhedrin.hrl").
%% API
-export([start_link/0, check_case/1, check_vote/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-define(SERVER, ?MODULE).
-record(state, {
halt_count = 0 :: non_neg_integer(),
halt_log = [] :: [{integer(), atom(), binary()}]
}).
%%====================================================================
%% API
%%====================================================================
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%% @doc Check a case submission for halt conditions.
%% Returns 'clear' or {halt, Condition, Reason}.
-spec check_case(#sanhedrin_case{}) -> clear | {halt, atom(), binary()}.
check_case(Case) ->
gen_server:call(?SERVER, {check_case, Case}).
%% @doc Check a vote for halt conditions.
-spec check_vote(#vote{}) -> clear | {halt, atom(), binary()}.
check_vote(Vote) ->
gen_server:call(?SERVER, {check_vote, Vote}).
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([]) ->
{ok, #state{}}.
handle_call({check_case, Case}, _From, State) ->
Result = do_check_case(Case),
NewState = maybe_log_halt(Result, State),
{reply, Result, NewState};
handle_call({check_vote, Vote}, _From, State) ->
Result = do_check_vote(Vote),
NewState = maybe_log_halt(Result, State),
{reply, Result, NewState};
handle_call(_Request, _From, State) ->
{reply, {error, unknown_request}, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
%%====================================================================
%% Internal — Halt condition checks
%%====================================================================
do_check_case(Case) ->
Context = Case#sanhedrin_case.context,
with_chain([
fun() -> check_avodah_zarah(Context) end,
fun() -> check_shfichut_damim(Context) end,
fun() -> check_gilui_arayot(Context) end
]).
do_check_vote(Vote) ->
%% Check vote content for halt conditions
Position = Vote#vote.position,
with_chain([
fun() -> check_authority_in_text(Position) end
]).
%% Run checks in chain — return first halt or clear
with_chain([]) -> clear;
with_chain([Check | Rest]) ->
case Check() of
clear -> with_chain(Rest);
Halt -> Halt
end.
%%--------------------------------------------------------------------
%% 1. Avodah Zarah — idolatry detection
%%--------------------------------------------------------------------
check_avodah_zarah(Context) ->
%% Check if any non-Torah source is treated as authoritative
AuthoritySource = maps:get(authority_source, Context, torah),
ValidSources = [torah, l1, specification, sanhedrin_deliberation],
case lists:member(AuthoritySource, ValidSources) of
true -> clear;
false ->
{halt, avodah_zarah,
iolist_to_binary([
<<"Non-Torah authority detected: ">>,
atom_to_binary(AuthoritySource, utf8)
])}
end.
%%--------------------------------------------------------------------
%% 2. Shfichut Damim — destruction detection
%%--------------------------------------------------------------------
check_shfichut_damim(Context) ->
%% Check if the case would result in destruction
Action = maps:get(action, Context, read),
DestructiveActions = [delete, destroy, overwrite, erase],
case lists:member(Action, DestructiveActions) of
true ->
{halt, shfichut_damim,
iolist_to_binary([
<<"Destructive action: ">>,
atom_to_binary(Action, utf8)
])};
false -> clear
end.
%%--------------------------------------------------------------------
%% 3. Gilui Arayot — boundary violation detection
%%--------------------------------------------------------------------
%% The 13 required distinctions that must never collapse:
%% specification/interpretation, L1/L3, Torah/external_model,
%% ketiv/qere, governance/provision, majority/minority,
%% reception/processing, read/write, immutable/mutable,
%% sacred/profane, Shabbat/weekday, input/output, human/system
check_gilui_arayot(Context) ->
BoundaryViolation = maps:get(boundary_violation, Context, none),
case BoundaryViolation of
none -> clear;
false -> clear;
Violation ->
{halt, gilui_arayot,
iolist_to_binary([
<<"Boundary collapsed: ">>,
io_lib:format("~p", [Violation])
])}
end.
%%--------------------------------------------------------------------
%% Text-level authority check (for vote content)
%%--------------------------------------------------------------------
check_authority_in_text(_Position) ->
%% Phase 2: basic check. Phase 3 will use Talmudic Engine
%% to detect authority attribution in natural language.
clear.
%%--------------------------------------------------------------------
%% Logging
%%--------------------------------------------------------------------
maybe_log_halt(clear, State) -> State;
maybe_log_halt({halt, Condition, Reason}, State) ->
Now = erlang:system_time(millisecond),
Entry = {Now, Condition, Reason},
State#state{
halt_count = State#state.halt_count + 1,
halt_log = [Entry | State#state.halt_log]
}.