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>
237 lines
7.4 KiB
Elixir
237 lines
7.4 KiB
Elixir
defmodule VavPipeline.Bikurim do
|
|
@moduledoc """
|
|
First Fruits — Release Protocol. Devarim 26:1-11.
|
|
|
|
Architecture §3.16:
|
|
First-output review process for all new capabilities.
|
|
Before a new feature serves users, its first product is
|
|
offered to the specification for evaluation, accompanied
|
|
by narrative.
|
|
|
|
Arami oved avi — "A wandering Aramean was my father."
|
|
— Devarim 26:5
|
|
|
|
The offering includes NARRATIVE. Not just what was produced,
|
|
but the story of how it was produced and what lineage it carries.
|
|
The farmer does not just bring fruit. He tells the story of
|
|
his ancestors' wandering, Egypt, the exodus, and arrival.
|
|
|
|
Protocol:
|
|
1. New capability built → first output produced
|
|
2. Builder provides narrative (the mikra bikurim):
|
|
- What was built
|
|
- What specification authorized it
|
|
- What lineage it carries (which existing components it depends on)
|
|
- What Torah grounds it
|
|
3. First output evaluated against specification
|
|
4. Accepted → recorded in registry, approved for production
|
|
5. Rejected → recorded with reason, not deployed
|
|
|
|
The offering is placed "before Hashem your God" — lifnei Hashem
|
|
Elohekha (Devarim 26:10). The specification judges. Not the builder.
|
|
Not the operator. The specification.
|
|
"""
|
|
|
|
use GenServer
|
|
|
|
require Logger
|
|
|
|
alias VavPipeline.Specification
|
|
|
|
@type offering_status :: :accepted | :rejected | :pending
|
|
@type offering :: %{
|
|
capability: String.t(),
|
|
first_output: any(),
|
|
narrative: String.t(),
|
|
lineage: [String.t()],
|
|
torah_grounding: String.t() | nil,
|
|
offered_at: DateTime.t(),
|
|
status: offering_status(),
|
|
evaluation: map() | nil
|
|
}
|
|
|
|
# ============================================================
|
|
# Client API
|
|
# ============================================================
|
|
|
|
def start_link(opts \\ []) do
|
|
name = Keyword.get(opts, :name, __MODULE__)
|
|
GenServer.start_link(__MODULE__, opts, name: name)
|
|
end
|
|
|
|
@doc """
|
|
Offer first fruit — submit a new capability's first output for review.
|
|
|
|
Devarim 26:2 — V'lakachta mereshit kol p'ri ha'adamah...
|
|
"You shall take of the first of every fruit of the ground..."
|
|
|
|
Parameters:
|
|
- capability_name: identifier for the new capability
|
|
- first_output: the actual first product
|
|
- narrative: the mikra bikurim — the story of how this was built
|
|
- opts: keyword list with optional :lineage and :torah_grounding
|
|
|
|
Returns {:ok, :approved_for_deployment, offering} or
|
|
{:error, :specification_mismatch, reason, offering}.
|
|
"""
|
|
@spec offer(String.t(), any(), String.t(), keyword()) ::
|
|
{:ok, :approved_for_deployment, offering()}
|
|
| {:error, :specification_mismatch, String.t(), offering()}
|
|
def offer(capability_name, first_output, narrative, opts \\ [])
|
|
when is_binary(capability_name) and is_binary(narrative) do
|
|
GenServer.call(__MODULE__, {:offer, capability_name, first_output, narrative, opts})
|
|
end
|
|
|
|
@doc """
|
|
Get all offerings in the registry.
|
|
"""
|
|
@spec registry() :: [offering()]
|
|
def registry do
|
|
GenServer.call(__MODULE__, :registry)
|
|
end
|
|
|
|
@doc """
|
|
Get offerings by status.
|
|
"""
|
|
@spec by_status(offering_status()) :: [offering()]
|
|
def by_status(status) when status in [:accepted, :rejected, :pending] do
|
|
GenServer.call(__MODULE__, {:by_status, status})
|
|
end
|
|
|
|
@doc """
|
|
Check if a capability has been accepted (approved for deployment).
|
|
"""
|
|
@spec approved?(String.t()) :: boolean()
|
|
def approved?(capability_name) do
|
|
GenServer.call(__MODULE__, {:approved?, capability_name})
|
|
end
|
|
|
|
@doc """
|
|
Count offerings by status.
|
|
"""
|
|
@spec count(offering_status() | :all) :: non_neg_integer()
|
|
def count(filter \\ :all) do
|
|
GenServer.call(__MODULE__, {:count, filter})
|
|
end
|
|
|
|
# ============================================================
|
|
# GenServer callbacks
|
|
# ============================================================
|
|
|
|
@impl true
|
|
def init(_opts) do
|
|
state = %{
|
|
# All offerings — append-only registry
|
|
offerings: []
|
|
}
|
|
|
|
Logger.info("Bikurim: first fruits protocol ready — reshit kol p'ri ha'adamah")
|
|
{:ok, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:offer, capability_name, first_output, narrative, opts}, _from, state) do
|
|
now = DateTime.utc_now()
|
|
lineage = Keyword.get(opts, :lineage, [])
|
|
torah_grounding = Keyword.get(opts, :torah_grounding)
|
|
|
|
offering = %{
|
|
capability: capability_name,
|
|
first_output: first_output,
|
|
narrative: narrative,
|
|
lineage: lineage,
|
|
torah_grounding: torah_grounding,
|
|
offered_at: now,
|
|
status: :pending,
|
|
evaluation: nil
|
|
}
|
|
|
|
# Evaluate against specification — lifnei Hashem Elohekha
|
|
case evaluate_against_specification(offering) do
|
|
:accepted ->
|
|
accepted = %{offering | status: :accepted, evaluation: %{result: :accepted}}
|
|
|
|
Logger.info(
|
|
"Bikurim: #{capability_name} accepted — first fruit approved for deployment"
|
|
)
|
|
|
|
new_state = %{state | offerings: [accepted | state.offerings]}
|
|
{:reply, {:ok, :approved_for_deployment, accepted}, new_state}
|
|
|
|
{:rejected, reason} ->
|
|
rejected = %{
|
|
offering
|
|
| status: :rejected,
|
|
evaluation: %{result: :rejected, reason: reason}
|
|
}
|
|
|
|
Logger.warning(
|
|
"Bikurim: #{capability_name} rejected — #{reason}"
|
|
)
|
|
|
|
new_state = %{state | offerings: [rejected | state.offerings]}
|
|
{:reply, {:error, :specification_mismatch, reason, rejected}, new_state}
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def handle_call(:registry, _from, state) do
|
|
{:reply, state.offerings, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:by_status, status}, _from, state) do
|
|
matching = Enum.filter(state.offerings, &(&1.status == status))
|
|
{:reply, matching, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:approved?, capability_name}, _from, state) do
|
|
approved =
|
|
Enum.any?(state.offerings, fn o ->
|
|
o.capability == capability_name and o.status == :accepted
|
|
end)
|
|
|
|
{:reply, approved, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:count, :all}, _from, state) do
|
|
{:reply, length(state.offerings), state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:count, status}, _from, state) do
|
|
count = Enum.count(state.offerings, &(&1.status == status))
|
|
{:reply, count, state}
|
|
end
|
|
|
|
# ============================================================
|
|
# Specification evaluation
|
|
# ============================================================
|
|
|
|
defp evaluate_against_specification(offering) do
|
|
# The specification evaluates the offering. Three checks:
|
|
# 1. Does the capability have a narrative? (Arami oved avi — story is required)
|
|
# 2. Does the first output conform to the specification?
|
|
# 3. Is the Torah grounding valid?
|
|
|
|
cond do
|
|
# No narrative — the bikurim requires the mikra (recitation)
|
|
String.trim(offering.narrative) == "" ->
|
|
{:rejected, "No narrative provided — Devarim 26:5 requires the mikra bikurim"}
|
|
|
|
# Check against specification module if available
|
|
Code.ensure_loaded?(Specification) and function_exported?(Specification, :evaluate_bikurim, 1) ->
|
|
apply(Specification, :evaluate_bikurim, [offering])
|
|
|
|
# Default: accept if narrative is present and first_output is not nil
|
|
is_nil(offering.first_output) ->
|
|
{:rejected, "No first output provided — there must be fruit to offer"}
|
|
|
|
true ->
|
|
:accepted
|
|
end
|
|
end
|
|
end
|