diff --git a/vav_pipeline/lib/vav_pipeline/l1_reader.ex b/vav_pipeline/lib/vav_pipeline/l1_reader.ex index a3134ef5..69e3aae4 100644 --- a/vav_pipeline/lib/vav_pipeline/l1_reader.ex +++ b/vav_pipeline/lib/vav_pipeline/l1_reader.ex @@ -120,6 +120,27 @@ defmodule VavPipeline.L1Reader do @doc """ Extract roots from a verse with gematria values. + + PROVENANCE NOTE — single-opinion derivation: + + The shoresh value on each word comes from the OSHB (Open Scriptures + Hebrew Bible) lemma database via build_l1.py. OSHB pins one root + per word at build time; the L1 JSON does not record which + derivational opinion produced it. For triliteral roots the choice + is rarely contested, but for weak roots and biliterals it matters + constantly — e.g. for וְנָתַתִּי (Devarim 11:14) OSHB records the + biliteral נת, while classical analysis often gives נתן with + assimilated nun. Both are defensible; OSHB picked one. + + Downstream consumers MUST NOT treat the returned shoresh as + unique-truth. The Talmudic Engine should record the derivational + source as part of its coupling_trace when a shoresh-based ruling + enters L3 — otherwise a future re-derivation cannot be reconciled + with prior opinions stored on top of the OSHB choice. + + This function returns a flat root → gematria map. To preserve + derivational alternatives, that work belongs in the build_l1.py + enrichment pass, not here. """ @spec extract_roots(verse()) :: map() def extract_roots(verse) do @@ -315,6 +336,37 @@ defmodule VavPipeline.L1Reader do # Melekh = disjunctor (emperor/king), Mesharet = conjunctor (servant) # Spellings must match what build_l1.py writes to L1 JSON. # Verified against actual L1 data (bereishit-devarim ch1 sample). + # + # Classification principle (the WHY behind the two lists): + # + # Each ta'am is either MELEKH or MESHARET. The classification is + # not a stylistic preference — it is structural. A melekh stands + # alone and ends a phrase; a mesharet only joins to the following + # word and cannot stand alone. The diagnostic test: + # + # "Can this ta'am occupy the position of sof-pasuk-equivalent + # in some valid context?" → if yes, melekh. + # "Does this ta'am only occur in service of a following melekh, + # binding two words into one syntactic unit?" → if yes, mesharet. + # + # The hierarchy of melakhim (sof_pasuk → etnachta → zaqef → tipcha + # → revia → …) corresponds to syntactic depth: each level marks + # the cut for one level of clausal subdivision. The mesharetim + # (munach, mercha, mahapakh, darga, qadma, telisha_qetana, + # yerah_ben_yomo) precede their melakhim — the servant goes + # before the king. + # + # This classification is binding for the pipeline's havdalah + # (separation) operation: only melakhim are valid phrase-cut + # points. Treating a mesharet as a phrase-end would falsify the + # text's own divisions — a small gilui_arayot (collapsing the + # disjunctor/conjunctor distinction). + # + # Source authority: this is the consensus Masoretic position + # documented in Yeivin's "Introduction to the Tiberian + # Masorah" (1980) §174-§268. The lists below match what + # build_l1.py emits from the OSHB JSON; if OSHB ever encodes a + # ta'am with a different name, BOTH lists must be updated. @melekh_marks ~w(sof_pasuk etnachta segol_accent shalshelet zaqef_qatan zaqef_gadol tipcha revia zarqa pashta yetiv tevir geresh gershayim pazer telisha_gedola meteg_siluq zinor geresh_muqdam)