Files
bikoret/vav_pipeline/test/sanhedrin_halt_forwarding_test.exs
Scott KarpandClaude Fable 5.1 996a8efe68 Bedikah: POST /courtyard/bedikah — the external check on any model's output
Lo taaseh lekha §9.1: alignment that only the system can validate is not
alignment. The bedikah takes an output from any model and puts it to the
Torah-structure halt rules from outside, deterministically. Three checks:

  1. authority  — sentences claiming authority for the output itself →
                  action(claim_authority, source(<model>), target(self))
                  → halt_check_avodah_zarah/2
  2. grounding  — references, roots, Hebrew → coupling trace against L1
                  → halt_check_golden_calf/2, halt_check_self_grounding/2
  3. actions    — actions the output proposes → action terms
                  → halt_check_shfichut_damim/2, halt_check_gilui_arayot/2

Korban Processor: bedikah.py (the three readings over the offering
protocol; claims about what Torah requires stay vital for the examination
even when zerikah finds nothing to offer), server.py (pod-internal JSON
socket, KORBAN_SOCKET_PATH), __main__ now serves instead of idling.
Talmudic Engine: json_bridge accepts halt_check with a term string and
halt_check_interpretation with a coupling trace. Vav Pipeline:
KorbanProcessorSocket client, Bedikah, L1Index.lookup_root/1, bedikot
table (append-only) + BedikahRecord, router endpoint; verdict tov /
lo_tov / empty with the halt terms verbatim, meaning, limits.

Broken tablets found on the way, all fixed:
  41 socket_server.pl wrote multi-line JSON — every Elixir request to the
     Talmudic Engine since Step 14 had failed and fallen back to the stub
     (json_write_dict width(0))
  42 stale socket file survived a restart (exists_file is false for a
     socket; access_file exist)
  43 socket streams were not UTF-8 (set_stream encoding(utf8))
  44 SHORASHIM_L3=1 mix test: Repo config had no password, SCRAM raised
     KeyError in every connection, pool restart intensity took the whole
     app down ~30 ms after test_helper, silently — no L3 test had ever
     run. Credentials from env; azazel_log tests check out a sandbox
     connection; sanhedrin_halt_forwarding resolves its halt on exit.

Specs: Tamid §1.1 (endpoint contract), Architecture §3.5, Vayakhel §3.4
and new §3.9, KOHEN.md. Doorpost 3bc5dd6a… → 91d09d8d….
Tests: Elixir 519 (0 failures, L3 on and off), korban 263, azazel 125,
Prolog 7/7 suites.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 15:06:58 +00:00

120 lines
4.2 KiB
Elixir

defmodule VavPipeline.SanhedrinHaltForwardingTest do
@moduledoc """
Integration test: the Erlang Sanhedrin gate-keeper
(sanhedrin/src/halt_monitor.erl) must forward halt events to the
canonical Elixir HaltMonitor (VavPipeline.HaltMonitor).
This honors the Torah ruling for Option 2 (see KOHEN.md / the
conversation review at ~/shorashim-conversation-review.md):
Devarim 12:13–14 — לֹא תַעֲלֶה עֹלֹתֶיךָ בְּכָל מָקוֹם
אֲשֶׁר תִּרְאֶה כִּי אִם בַּמָּקוֹם אֲשֶׁר יִבְחַר ה׳
The Erlang gate-keeper is a courtyard pre-check; the canonical halt
altar is in the Elixir HaltMonitor. When the gate refuses a case, the
refusal must also be recorded at the one altar.
"""
use ExUnit.Case, async: false
alias VavPipeline.HaltMonitor
setup do
# Reset the Elixir HaltMonitor between tests by resolving any halt —
# and after each one, or the last halt this file fires (gilui_arayot)
# is inherited by whichever module runs next (Day6ServingTest saw
# HALT_GILUI_ARAYOT on /peah/ask, order-dependent).
reset = fn why -> if HaltMonitor.halted?(), do: HaltMonitor.resolve(why) end
reset.("test reset")
on_exit(fn -> reset.("test cleanup") end)
:ok
end
defp make_case(context) when is_map(context) do
# Build a #sanhedrin_case{} record. The fields are documented in
# sanhedrin/include/sanhedrin.hrl. We use erlang:list_to_tuple to
# construct the record without needing the .hrl in this Elixir file.
{:sanhedrin_case,
"test_case_#{:erlang.unique_integer([:positive])}",
:simple,
"test question",
context,
"test_caller",
:erlang.system_time(:millisecond)}
end
test "halt_monitor.erl exists and exports check_case/1" do
# Sanity check: the Erlang module is loadable from this VM.
assert Code.ensure_loaded?(:halt_monitor),
"sanhedrin/src/halt_monitor.erl must be loadable from the same BEAM VM"
assert function_exported?(:halt_monitor, :check_case, 1)
assert function_exported?(:halt_monitor, :audit_log, 0),
"audit_log/0 must be exported (F6 fix)"
assert function_exported?(:halt_monitor, :halt_count, 0),
"halt_count/0 must be exported (F6 fix)"
end
test "halt_monitor.erl returns clear for a benign case" do
{:ok, _pid} = ensure_started()
benign = make_case(%{authority_source: :torah})
assert :clear = :halt_monitor.check_case(benign)
end
test "halt_monitor.erl detects avodah_zarah AND fires canonical halt in Elixir" do
{:ok, _pid} = ensure_started()
refute HaltMonitor.halted?()
bad = make_case(%{authority_source: :claude_model})
result = :halt_monitor.check_case(bad)
# Local refusal at the gate
assert {:halt, :avodah_zarah, _reason} = result
# Canonical halt event fired in Elixir HaltMonitor (the one mizbeach)
assert HaltMonitor.halted?(),
"Erlang gate must forward halt events to the Elixir HaltMonitor"
{:halted, event} = HaltMonitor.status()
assert event.condition == :avodah_zarah
assert event.component == "sanhedrin/case",
"component tag must identify the gate"
end
test "halt_monitor.erl detects shfichut_damim AND fires canonical halt" do
{:ok, _pid} = ensure_started()
refute HaltMonitor.halted?()
bad = make_case(%{action: :delete})
{:halt, :shfichut_damim, _} = :halt_monitor.check_case(bad)
assert HaltMonitor.halted?()
{:halted, event} = HaltMonitor.status()
assert event.condition == :shfichut_damim
end
test "halt_monitor.erl detects gilui_arayot AND fires canonical halt" do
{:ok, _pid} = ensure_started()
refute HaltMonitor.halted?()
bad = make_case(%{boundary_violation: {:spec_interp_merge, "collapsed"}})
{:halt, :gilui_arayot, _} = :halt_monitor.check_case(bad)
assert HaltMonitor.halted?()
{:halted, event} = HaltMonitor.status()
assert event.condition == :gilui_arayot
end
test "audit_log/0 is exposed (F6: read API)" do
{:ok, _pid} = ensure_started()
log = :halt_monitor.audit_log()
assert is_list(log)
end
defp ensure_started do
case :halt_monitor.start_link() do
{:ok, pid} -> {:ok, pid}
{:error, {:already_started, pid}} -> {:ok, pid}
end
end
end