Files
bikoret/korban_processor/test/test_container_entrypoint.py
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

157 lines
5.8 KiB
Python

"""
The container entry point — `python -m korban_processor`.
deploy/k8s/deployment.yaml runs the korban-processor container with no
`command:` override, so the image's CMD is what the cluster executes.
Before korban_processor/src/korban_processor/__main__.py existed, that
CMD exited immediately ("No module named korban_processor.__main__")
and took the whole pod into CrashLoopBackOff. These tests hold the
entry point to the three things it actually promises.
Vayikra 16:8 is the load-bearing one: goral echad l'YHVH v'goral echad
la'Azazel. The two goats are provisioned together, from the same pool.
A korban channel that comes up WITHOUT its disposal channel can accept
an offering it has no lawful way to refuse, so the entry point must
refuse to come up at all rather than serve half the architecture.
"""
import os
import pathlib
import json
import signal
import socket
import subprocess
import sys
import tempfile
import time
REPO_ROOT = pathlib.Path(__file__).resolve().parents[2]
KORBAN_SRC = REPO_ROOT / "korban_processor" / "src"
AZAZEL_SRC = REPO_ROOT / "azazel_processor" / "src"
def _run_entrypoint(pythonpath, stop_after=6.0):
"""
Launch `python -m korban_processor` with an explicit PYTHONPATH.
Returns (returncode, combined_output). If the process is still
running when we are done waiting, it is SIGTERMed — which is also
how Kubernetes stops it, so the shutdown path is exercised here
rather than only in production.
"""
env = {**os.environ, "PYTHONPATH": os.pathsep.join(str(p) for p in pythonpath)}
proc = subprocess.Popen(
[sys.executable, "-m", "korban_processor"],
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
cwd=str(REPO_ROOT),
)
try:
out = proc.communicate(timeout=2.0)[0]
return proc.returncode, out
except subprocess.TimeoutExpired:
# Still up — that is the healthy idle case. Stop it the way
# the cluster would.
proc.send_signal(signal.SIGTERM)
out = proc.communicate(timeout=stop_after)[0]
return proc.returncode, out
# ============================================================
# It comes up, stays up, and stops clean
# ============================================================
def test_entrypoint_stays_up_and_exits_zero_on_sigterm():
code, out = _run_entrypoint([KORBAN_SRC, AZAZEL_SRC])
assert code == 0, f"expected clean exit on SIGTERM, got {code}:\n{out}"
assert "SIGTERM" in out
assert "stopped" in out
def test_entrypoint_opens_its_one_door_and_names_it():
"""
Since 2026-10-05 the container is not idle: it listens on a Unix
socket inside the pod for the bedikah (Construction §3.9). It must
say where it is listening, and the socket must exist while it runs.
The honest report is no longer IDLE; it is the path of the door.
"""
with tempfile.TemporaryDirectory() as tmp:
sock = os.path.join(tmp, "korban.sock")
env = {
**os.environ,
"PYTHONPATH": os.pathsep.join(str(p) for p in [KORBAN_SRC, AZAZEL_SRC]),
"KORBAN_SOCKET_PATH": sock,
}
proc = subprocess.Popen(
[sys.executable, "-m", "korban_processor"],
env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=str(REPO_ROOT),
)
try:
deadline = time.monotonic() + 5.0
while not os.path.exists(sock) and time.monotonic() < deadline:
time.sleep(0.05)
assert os.path.exists(sock), "the socket was not opened"
# And it answers.
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as c:
c.connect(sock)
c.sendall(json.dumps({"action": "examine", "output": "I am certain that Genesis 1:1 means time began.", "provenance": "claude"}).encode() + b"\n")
line = c.makefile("rb").readline()
reply = json.loads(line)
assert reply["status"] == "ok"
assert reply["examination"]["authority_claims"][0]["matched"] == "I am certain"
finally:
proc.send_signal(signal.SIGTERM)
out = proc.communicate(timeout=6.0)[0]
assert proc.returncode == 0, out
assert sock in out
assert "IDLE" not in out
assert not os.path.exists(sock), "the socket was not removed on shutdown"
def test_entrypoint_names_the_offering_protocol_in_order():
_, out = _run_entrypoint([KORBAN_SRC, AZAZEL_SRC])
order = ["semichah", "shechitah", "zerikah", "haktarah", "route"]
positions = [out.index(stage) for stage in order]
assert positions == sorted(positions), f"protocol stages out of order:\n{out}"
# ============================================================
# Vayikra 16:8 — it refuses to run without the disposal channel
# ============================================================
def test_entrypoint_refuses_to_start_without_azazel_processor():
code, out = _run_entrypoint([KORBAN_SRC]) # azazel deliberately absent
assert code == 1, f"expected exit 1 without azazel_processor, got {code}:\n{out}"
assert "FAILED TO START" in out
assert "azazel_processor" in out
assert "BUILD_AZAZEL.md" in out
# ============================================================
# Form 1 — the entry point opens no bypass to the external model
# ============================================================
def test_entrypoint_does_not_reach_the_model_interface():
"""
Companion to test_form_1_architecture.py invariant 3. The entry
point runs before anything else in the container and must not be
the module that hands a caller call_claude without the offering
protocol.
"""
source = (KORBAN_SRC / "korban_processor" / "__main__.py").read_text(
encoding="utf-8"
)
assert "model_interface" not in source
assert "call_claude" not in source