l1_reader: document te'amim classification principle and shoresh derivation provenance
Two related Pass 2 findings — both about UNSTATED reasoning behind
hard-coded lists in L1Reader.
Finding G — te'amim classification principle:
@melekh_marks and @mesharet_marks were lists of strings with no
documented rule for which marks belong to which class. A future
reader saw the lists but not the deliberation. Added classification
principle to the comment block:
- The diagnostic test: can the ta'am occupy a sof-pasuk-equivalent
position? → melekh. Does it only serve a following melekh? →
mesharet.
- The hierarchy of melakhim corresponds to syntactic depth
(sof_pasuk → etnachta → zaqef → tipcha → revia → …).
- Mesharetim precede their melakhim — the servant goes before
the king.
- The classification is BINDING for havdalah: treating a mesharet
as a phrase-end is a small gilui_arayot.
- Source authority: Yeivin's Tiberian Masorah §174-§268.
- Maintenance rule: if OSHB ever encodes a ta'am with a different
name, BOTH lists must be updated.
Finding H — shoresh derivation provenance:
extract_roots/1 returned a flat root → gematria map without recording
which derivational opinion produced each shoresh. For triliterals
this rarely matters; for weak roots and biliterals it matters
constantly (e.g. וְנָתַתִּי in Devarim 11:14 — OSHB records נת,
classical analysis often gives נתן with assimilated nun). Added
provenance note to the function docstring:
- The shoresh comes from OSHB lemma database via build_l1.py
- OSHB pins one root per word at build time; L1 JSON does not
record which derivational opinion produced it
- Downstream consumers MUST NOT treat the returned shoresh as
unique-truth
- The Talmudic Engine should record the derivational source
in 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
- Preserving derivational alternatives belongs in the build_l1.py
enrichment pass, not in this read function
Both docstrings make the WHY visible; the WHAT was already there.
No code change. Tests pass unchanged (288 in vav_pipeline,
8 in shema_voice_trajectory_test).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
af2a3949cf
commit
d3869c5b75
1 file changed
+52
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user