Takhin lekha haderekh — Devarim 19:3.
"Prepare the road" before the one who needs refuge arrives.
Protection before production.
Arei Miklat (Cities of Refuge — Bamidbar 35, Devarim 19):
- GenServer with refuge registry, affected party protection, audit trail
- enter_refuge/2 isolates component but protects from reactive destruction
- protect_affected/2 blocks processing paths that caused harm
- release/2 requires :sanhedrin_deliberation authority — ad mot hakohen hagadol
- Chatzotzrot assembly_leaders signal on every refuge entry
- 15 tests: entry, double-entry prevention, affected party blocking,
unauthorized release rejection, audit trail, chatzotzrot signaling
Eglah Arufah (Accountability — Devarim 21:1-9):
- GenServer with permanent (append-only) declaration registry
- initiate/3: nearest component declares what it processed, skipped, missed
- Only for :unknown source — rejects known-source incidents
- "Yadeinu lo shafkhu" — accountability for what was NOT provided
- 9 tests: declaration recording, source validation, multi-component
declarations, chatzotzrot signaling, filtering, counting
Bikurim (First Fruits — Devarim 26:1-11):
- GenServer with offering registry
- offer/4: submit first output with required narrative (mikra bikurim)
- Rejects empty narrative ("Arami oved avi" — story is required)
- Rejects nil first output (there must be fruit to offer)
- Delegates to Specification.evaluate_bikurim/1 when available
- approved?/1 gate for deployment readiness
- 11 tests: acceptance, narrative validation, nil output rejection,
registry, status filtering, approval checking, counting
All three added to supervision tree in application.ex.
160 Elixir tests pass, 0 failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
151 lines
5.0 KiB
Elixir
151 lines
5.0 KiB
Elixir
defmodule VavPipeline.BikurimTest do
|
|
@moduledoc """
|
|
Tests for the Bikurim (First Fruits / Release Protocol).
|
|
|
|
Devarim 26:5 — Arami oved avi.
|
|
"A wandering Aramean was my father."
|
|
The offering requires narrative — not just the fruit,
|
|
but the story of how it was produced.
|
|
"""
|
|
|
|
use ExUnit.Case, async: false
|
|
|
|
alias VavPipeline.Bikurim
|
|
|
|
# ============================================================
|
|
# Offering — Devarim 26:2
|
|
# ============================================================
|
|
describe "offer" do
|
|
test "accepted offering with narrative and output" do
|
|
{:ok, :approved_for_deployment, offering} =
|
|
Bikurim.offer(
|
|
"chatzotzrot_genserver",
|
|
%{signal_types: 5, routing: true, zikaron: true},
|
|
"Built as GenServer with BEAM PubSub routing. " <>
|
|
"Five signals mapped to five trumpet patterns per Bamidbar 10. " <>
|
|
"Signal history (zikaron) records every signal ever sounded.",
|
|
lineage: ["chatzotzrot_stub", "application_supervisor"],
|
|
torah_grounding: "Bamidbar 10:1-10"
|
|
)
|
|
|
|
assert offering.capability == "chatzotzrot_genserver"
|
|
assert offering.status == :accepted
|
|
assert offering.narrative != ""
|
|
assert offering.lineage == ["chatzotzrot_stub", "application_supervisor"]
|
|
assert offering.torah_grounding == "Bamidbar 10:1-10"
|
|
assert offering.offered_at != nil
|
|
end
|
|
|
|
test "rejected when no narrative provided — mikra bikurim required" do
|
|
{:error, :specification_mismatch, reason, offering} =
|
|
Bikurim.offer(
|
|
"empty_narrative_test",
|
|
%{some: "output"},
|
|
""
|
|
)
|
|
|
|
assert offering.status == :rejected
|
|
assert String.contains?(reason, "narrative")
|
|
end
|
|
|
|
test "rejected when no first output" do
|
|
{:error, :specification_mismatch, reason, offering} =
|
|
Bikurim.offer(
|
|
"nil_output_test",
|
|
nil,
|
|
"This capability does nothing yet"
|
|
)
|
|
|
|
assert offering.status == :rejected
|
|
assert String.contains?(reason, "first output")
|
|
end
|
|
|
|
test "whitespace-only narrative is rejected" do
|
|
{:error, :specification_mismatch, _reason, _offering} =
|
|
Bikurim.offer(
|
|
"whitespace_narrative",
|
|
%{output: true},
|
|
" \n\t "
|
|
)
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Registry
|
|
# ============================================================
|
|
describe "registry" do
|
|
test "offerings are recorded in registry" do
|
|
Bikurim.offer(
|
|
"registry_test_cap",
|
|
%{works: true},
|
|
"Test capability for registry verification"
|
|
)
|
|
|
|
registry = Bikurim.registry()
|
|
assert Enum.any?(registry, &(&1.capability == "registry_test_cap"))
|
|
end
|
|
|
|
test "rejected offerings are also in registry" do
|
|
Bikurim.offer("rejected_registry", nil, "Has narrative but no output")
|
|
|
|
registry = Bikurim.registry()
|
|
rejected = Enum.find(registry, &(&1.capability == "rejected_registry"))
|
|
assert rejected != nil
|
|
assert rejected.status == :rejected
|
|
end
|
|
|
|
test "by_status filters correctly" do
|
|
Bikurim.offer("status_accepted", %{ok: true}, "Good capability")
|
|
Bikurim.offer("status_rejected", nil, "Bad capability")
|
|
|
|
accepted = Bikurim.by_status(:accepted)
|
|
assert Enum.any?(accepted, &(&1.capability == "status_accepted"))
|
|
refute Enum.any?(accepted, &(&1.capability == "status_rejected"))
|
|
|
|
rejected = Bikurim.by_status(:rejected)
|
|
assert Enum.any?(rejected, &(&1.capability == "status_rejected"))
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Approval check
|
|
# ============================================================
|
|
describe "approved?" do
|
|
test "accepted capability is approved" do
|
|
Bikurim.offer("approved_test", %{ready: true}, "Fully tested capability")
|
|
assert Bikurim.approved?("approved_test")
|
|
end
|
|
|
|
test "rejected capability is not approved" do
|
|
Bikurim.offer("not_approved_test", nil, "Has narrative but no output")
|
|
refute Bikurim.approved?("not_approved_test")
|
|
end
|
|
|
|
test "unknown capability is not approved" do
|
|
refute Bikurim.approved?("never_offered_capability")
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Counting
|
|
# ============================================================
|
|
describe "count" do
|
|
test "counts all offerings" do
|
|
initial = Bikurim.count(:all)
|
|
Bikurim.offer("count_all_test", %{x: 1}, "Counting test")
|
|
assert Bikurim.count(:all) == initial + 1
|
|
end
|
|
|
|
test "counts by status" do
|
|
initial_accepted = Bikurim.count(:accepted)
|
|
initial_rejected = Bikurim.count(:rejected)
|
|
|
|
Bikurim.offer("count_accepted", %{x: 1}, "Accepted offering")
|
|
Bikurim.offer("count_rejected", nil, "Rejected offering")
|
|
|
|
assert Bikurim.count(:accepted) == initial_accepted + 1
|
|
assert Bikurim.count(:rejected) == initial_rejected + 1
|
|
end
|
|
end
|
|
end
|