defmodule VavPipeline.Tablet33EngineRootsTest do @moduledoc """ Tablet 33 (2026-10-04) — the Shoresh Engine now hears roots from L1 (shoresh-engine `Shoresh.Roots`), and its answers changed shape in three ways the cycle must carry faithfully: * a root is rendered exactly as L1 records it (two letters for בן, four for שמאל) — no padded He; * `binyan` is null for a noun, and for any word not in the verse; * a root heard through a word's lemma (`לבבך` → `לבב`) arrives with the `surface` word it was heard from, because L1 records no shoresh on the suffixed noun and the verse cannot be searched by shoresh. The engine's own behaviour is held by its HSpec suite (55 examples). This file holds the pipeline's reading of it, with an engine-shaped stand-in under the real port name answering as the rebuilt engine answered for Devarim 6:5 on 2026-10-04. """ use ExUnit.Case, async: false import Plug.Test import Plug.Conn alias VavPipeline.{HaltMonitor, MannaLedger} alias VavPipeline.BigdeiKodesh.Router @opts Router.init([]) defmodule EnginePort do use GenServer def start, do: GenServer.start(__MODULE__, :ok, name: VavPipeline.ShoreshEnginePort) @impl true def init(:ok), do: {:ok, :ok} @impl true def handle_call({:request, _json_line}, _from, s) do roots = [ root(["aleph", "he", "bet"], "אהב", 8, "Qal", "ואהבת", "verse"), root(["kaf", "lamed", "lamed"], "כלל", 80, nil, "בכל", "verse"), root(["yod", "resh", "dalet"], "ירד", 214, nil, "לבבך", "lemma") ] {:reply, {:ok, %{"roots_activated" => roots, "parse_tree" => nil, "dual_readings" => []}}, s} end defp root(letters, hebrew, gematria, binyan, surface, derivation) do %{ "shoresh" => letters, "shoresh_hebrew" => hebrew, "gematria_value" => gematria, "binyan" => binyan, "domain" => "unknown", "torah_refs" => [], "neighbors" => [], "gematria_neighbors" => [], "surface" => surface, "derivation" => derivation } end end setup do if HaltMonitor.halted?(), do: HaltMonitor.resolve("tablet33 test setup") write_provision(50) assert Process.whereis(VavPipeline.ShoreshEnginePort) == nil {:ok, pid} = EnginePort.start() on_exit(fn -> if Process.alive?(pid), do: GenServer.stop(pid) end) :ok end test "Devarim 6:5 — the engine's roots are placed in the verse and said plainly" do conn = post_ask("devarim 6:5") body = Jason.decode!(conn.resp_body) answer = body["answer"] assert conn.status == 200, "#{conn.status} #{conn.resp_body}" # A verb in the verse: binyan and position. assert answer =~ "א-ה-ב (gematria 8, Qal, word 1)" # A root stands wherever L1 gives a word that shoresh: בכל is word 5, # ובכל words 7 and 9 (L1, re-engraved in tablet 34, files כל under כלל). assert answer =~ "כ-ל-ל (gematria 80, word 5, 7, 9)" # A root L1 does not record on any word of the verse can only be # placed by the surface word the engine heard it from. (After tablet # 34 L1 does give לבבך its shoresh, so the stand-in reports a root # the verse does not carry, to hold the surface path shut.) Word 6 — # not "not in this verse". assert answer =~ "י-ר-ד (gematria 214, word 6)" refute answer =~ "not in this verse" refute answer =~ "binyan unknown" assert body["processing"]["roots_consulted"] == ["א-ה-ב", "כ-ל-ל", "י-ר-ד"] end defp write_provision(compute_units) do MannaLedger.reset() on_exit(fn -> MannaLedger.reset() end) today = Date.utc_today() |> Date.to_iso8601() expires = DateTime.utc_now() |> DateTime.add(6 * 3600) |> DateTime.to_iso8601() provision = %{ "date" => today, "provision" => %{ "compute_units" => compute_units, "memory_mb" => 512, "api_calls_external" => 5, "storage_delta_mb" => 2, "sanhedrin_panels_max" => 2 }, "type" => "regular", "expires_at" => expires, "written_by" => "tablet33_test", "written_at" => DateTime.utc_now() |> DateTime.to_iso8601() } path = VavPipeline.Manna.provision_file() File.mkdir_p!(Path.dirname(path)) File.write!(path, Jason.encode!(provision)) on_exit(fn -> File.rm(path) end) path end defp post_ask(question) do conn(:post, "/peah/ask", Jason.encode!(%{question: question})) |> put_req_header("content-type", "application/json") |> Router.call(@opts) end end