defmodule VavPipeline do @moduledoc """ The Bereishit processing cycle. Each step chains to the next via |> (vav-consecutive). CRITICAL: The pipeline does not begin with a processing step. It begins with RECEPTION. The ShemaContext is built first — the system hears before it speaks. Then every processing step operates WITHIN the received context, never modifying it. Na'aseh v'nishma — but the order of execution is: nishma (hear/receive context), THEN na'aseh (process within it). """ alias VavPipeline.{Shema, Cloud, Manna, BereishitCycle, Chatzotzrot} @type scope :: %{ book: String.t(), chapter: pos_integer(), verse: pos_integer() } @type input :: %{ source: String.t(), verse_scope: scope(), content: String.t() } @type cycle_result :: {:ok, map()} | {:rejected, String.t()} | {:unresolved, map()} | {:transition, atom()} | {:waiting, atom()} | {:halted, atom(), String.t()} @doc """ Process input through the Bereishit cycle. 1. Build ShemaContext (nishma — hear first) 2. Check cloud — if moving, signal breaking camp 3. Check manna — if absent, wait 4. Process through cycle stages (na'aseh — within what was received) """ @spec process(input()) :: cycle_result() def process(input) do # === NISHMA: Hear first === case Shema.receive_context(input.verse_scope) do {:error, reason} -> {:halted, :context_failed, reason} {:ok, context} -> # === Check cloud before anything else === case context.cloud_state do :moving -> Chatzotzrot.signal(:breaking_camp) {:transition, :cloud_lifted} {:major_transition, signal, _params} -> {:transition, signal} :cloud_not_visible -> {:waiting, :cloud_not_visible} :camped -> # === Check manna === case context.daily_provision do :no_provision -> {:waiting, :no_provision} _provision -> # === Gather: d'var yom b'yomo === # The file says provision exists; the LEDGER is what is # consumed from. Load (idempotent per date), release # yesterday's surplus if the day turned, take one compute # unit for this cycle. Kohen Day 6: the ledger had never # been consumed from — two live cycles left it at # cycle_date: nil, cycle_count: 0. case Manna.gather_for_cycle() do :ok -> # === NA'ASEH: Now process, within what was received === BereishitCycle.execute(input, context) {:waiting, reason} -> {:waiting, reason} end end end end end @doc """ Esh tamid — push a real input through the real cycle and report whether a result came back. tamid §2.1 check 7: "The processing pipeline accepts a test input and returns a result. If the fire has gone out: re-initialize pipeline." Until the kohen's Day-6 reading, /kodesh/health's `esh_tamid` was `ShabbatTimer.resting?/0` — it reported `pass` while /peah/ask was returning empty 500s. A health check that does not touch the serving path cannot see the serving path. The probe: - builds a real ShemaContext (nishma first, same as process/1) - honours the cloud — does not run on Shabbat or in transition - runs the full BereishitCycle on Bereishit 1:1 with Hebrew input - does NOT consume manna and does NOT write L3 (probe: true — see BereishitCycle.tohu/2 and erev_voker/2). The fire is checked; the day's bread is not eaten by the check, and the oral tradition is not padded with health pings. Returns {:ok, data} when the fire burns, or the same non-ok shapes process/1 returns. """ @spec tamid_probe() :: cycle_result() | {:error, String.t()} def tamid_probe do scope = %{book: "bereishit", chapter: 1, verse: 1} input = %{ source: "tamid", verse_scope: scope, content: "בראשית ברא אלהים", probe: true } case Shema.receive_context(scope) do {:error, reason} -> {:halted, :context_failed, reason} {:ok, context} -> case context.cloud_state do :camped -> BereishitCycle.execute(input, context) :moving -> {:transition, :cloud_lifted} {:major_transition, signal, _} -> {:transition, signal} :cloud_not_visible -> {:waiting, :cloud_not_visible} end end end @doc """ Verify the pipeline is operational. Checks L1 integrity, cloud state, and manna provision. """ @spec verify() :: :ok | {:error, String.t()} def verify do with :ok <- VavPipeline.L1Reader.verify_integrity(), {:ok, _} <- Cloud.check(), {:ok, _} <- Manna.check() do :ok end end end