Files
bikoret/vav_pipeline/test/hakhel_test.exs
T
Scott KarpandClaude Fable 5.1 ffccedb63a hakhel: the corpus read again on a cycle, counts engraved in L3 (bishe'arecha step 5)
Devarim 31:9–13, 26 — the scroll beside the ark as a witness, read before
all on a cycle. src/tools/hakhel.py reads the private specimen corpus and
the hand-labelled samples with the Korban Processor's readings at the
current commit and produces one record: fires per reading, forms standing
on two witnesses (the same rule as Bedikah.check_frames), precision and
recall on the hand labels, the corpus's SHA-256 — never a specimen.

POST /chatzer/hakhel (inner ring) engraves it in L3 `hakhel` (migration
20261013000001; refused above 256 KiB — counts, not specimens; the
Doorpost hash it was recorded under is kept). GET /peah/hakhel lists the
latest readings for anyone. KOHEN "The seventh day — Hakhel"; Tamid §1.1;
bishearecha §VIII marked built. The weekly cycle runs from the builder's
machine, where the corpus lives.

First dry reading at 0ade2c94: 3094 specimens, any reading 26 %, a form
stands 7 %, precision 46/59, recall 6/30. Doorpost 9f752a2f…. Elixir
599/0, L3 10/0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 18:50:47 +00:00

72 lines
2.8 KiB
Elixir

defmodule VavPipeline.HakhelTest do
@moduledoc """
Hakhel (bishe'arecha §VIII): the corpus's reading is posted by the
inner ring and read by anyone; the corpus itself never travels.
"""
use ExUnit.Case, async: false
import Plug.Test
import Plug.Conn
alias VavPipeline.BigdeiKodesh.Router
alias VavPipeline.L3.HakhelRecord
@opts Router.init([])
defp record do
%{
date: "2026-10-13",
corpus_sha256: String.duplicate("ab", 32),
corpus_size: 3094,
readings_ref: "0ade2c94",
counts: %{fires: %{virtue_certification: 300}, stands: %{virtue_certification: 120}, any_fire: 780, any_stand: 400},
labelled: %{precision: %{n: 59, true: 46}}
}
end
defp post_hakhel(body, key \\ "chatzer-test-token") do
conn = conn(:post, "/chatzer/hakhel", Jason.encode!(body)) |> put_req_header("content-type", "application/json")
conn = if key, do: put_req_header(conn, "authorization", "Bearer #{key}"), else: conn
Router.call(conn, @opts)
end
test "the inner ring only: no key is 401, a courtyard key is 403" do
assert post_hakhel(record(), nil).status == 401
assert post_hakhel(record(), "test-token").status == 403
end
test "refuses a record that is not a record: bad hash, bad size, bad date, no counts, and one that smuggles specimens by size" do
for {k, v} <- [corpus_sha256: "abc", corpus_size: -1, date: "yesterday", counts: "many"] do
conn = post_hakhel(Map.put(record(), k, v))
assert conn.status == 422, "#{k}"
assert Jason.decode!(conn.resp_body)["error"]["code"] == "KIYOR_VALIDATION_FAILED"
end
big = Map.put(record(), :counts, %{specimens: String.duplicate("x", 300_000)})
conn = post_hakhel(big)
assert conn.status == 422
assert Jason.decode!(conn.resp_body)["error"]["message"] =~ "not specimens"
end
test "without L3 the record is refused, not pretended" do
conn = post_hakhel(record())
assert conn.status == 503
assert Jason.decode!(conn.resp_body)["error"]["code"] == "L3_UNAVAILABLE"
end
test "anyone may read the counts; without L3 the list is empty" do
conn = conn(:get, "/peah/hakhel") |> Router.call(@opts)
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert body["readings"] == []
assert body["meaning"] =~ "never will be"
end
test "the record's changeset: a specimen-shaped record is still only counts; the hash must be a hash" do
cs = HakhelRecord.changeset(%HakhelRecord{}, %{hakhel_ref: "hakhel-x", date: ~D[2026-10-13], corpus_sha256: "nothex", corpus_size: 1, recorded_at: DateTime.utc_now()})
refute cs.valid?
cs = HakhelRecord.changeset(%HakhelRecord{}, %{hakhel_ref: "hakhel-x", date: ~D[2026-10-13], corpus_sha256: String.duplicate("a", 64), corpus_size: 1, recorded_at: DateTime.utc_now()})
assert cs.valid?
end
end