Files
bikoret/vav_pipeline/test/tablet33_engine_roots_test.exs
T
Scott KarpandClaude Fable 5.1 8e4f94c66f L1: the shoresh is read from the lexicon, not guessed (tablet 34)
L1's `shoresh` field was derived by stripping a prefix letter and a
suffix letter from the consonants and keeping the first three. וַיַּרְא
"and he saw" was engraved as ירא ("fear"); ויהי as יהי; שמים as שמ;
מזבח as מזב; הבאתי as בא. And parse_prefixes took a word's morphology
from the LAST morph segment, which for a suffixed word is the pronominal
suffix — so every suffixed noun and verb in Torah (לבבך, נפשך) was
classed as a suffix and written with no shoresh at all.

Every WLC word already carries its lemma, and the OSHB lexical index
files each lemma under its Brown-Driver-Briggs root (terumah §E2 named
BDB + Strong's as the root lexicon and marked it "needs consolidation").
scripts/build_l1.py now reads the root from that filing:

  main    the lemma is a root            23,750 words   וירא → ראה
  sub     filed under a root             31,066 words   מזבח → זבח
  single  stands alone in the lexicon     2,671 words   משה → משה
  none    no etymology recorded → absent  3,002 words   יוסף, מצרים
  particles, pronouns → absent, as before 19,493 words  את, אשר, כי

57,487 words carry a shoresh (was 51,836); 1,378 unique roots (was
2,608 fragments). Roots are written as the lexicon writes them — two
letters (בן), three, or more (שמאל).

WHAT CHANGED IN THE EDUT: only `shoresh`. Verified file by file — with
that one field removed, all 5,853 verse files are byte-identical to the
previous L1. Text, consonants, lemma, morph, te'amim, prefix, ketiv/
qere, large and small letters: untouched. The old builder, run against
the same morphhb checkout, reproduces the old hash exactly; the new
builder is deterministic (two runs, one hash).

  L1 SHA-256  99bbd07a…4ea377  →  156b1d27…d8c9d5
  sources     morphhb 3d15126 · HebrewLexicon 21c9add
              (recorded in l1/build_report.json)

Moved together, because they pin the hash or the count:
vav_pipeline L1Reader @l1_expected_hash · shoresh-engine Luchot.Firmware
(hash, uniqueRootCount) + Spec · azazel_processor goral._L1_INTEGRITY_HASH
· KOHEN.md / KOHEN_PROMPT.md gate · l1/README.md (new "Roots" section) ·
README.md (second quarry) · AGENTS.md · root_meanings.pl comment.
The Doorpost manifest is not touched; its hash does not move.

Note for the kohen: the goral's seed inherits the L1 hash, so lots cast
after this commit are cast from a different seed than the azazel
records already in L3. Those records are history and stand as written.

All five suites on the new L1: Elixir 461/0 (seeds 0 42 191243) ·
Haskell 55/0 · Prolog 6 suites exit 0 (swipl 9.2.2) · korban 222 passed
1 skipped · azazel 125 passed. Four images built; full local stack
(real engine binary, PostgreSQL 16 with SSL, migrations) answers
Bereishit 1:4 with ר-א-ה, health healthy, 6 interpretations in L3,
0 write failures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 17:44:02 +00:00

135 lines
4.5 KiB
Elixir
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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