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