engine: the verse facts are the whole scroll, derived from L1
torah_text.pl held 32 hand-written verses from Phase 1 — "the reasoning layer's view of the specification". With the cycle and the Sanhedrin now consulting the engine on every question (2026-10-19), that view showed: any root it knew lit the same handful, and bereishit 1:1 and devarim 6:4 were read in the same eleven verses. - scripts/build_engine_verses.py writes talmudic_engine/src/specification/l1_verses.pl from l1/torah: every verse, each word's shoresh as the engine names it (Hebrew → letter names, finals folded), the consonantal text as gloss, and the SHA-256 of the L1 files read in the header. `--check` exits 1 when the facts lag the scroll; build_and_push.sh runs it beside the Doorpost check. - torah_text.pl includes the generated file; the hand facts are gone. L1's roots are authoritative where the hand facts differed (Israel שרה, the Name הוה). - interpret.pl: over 5,853 verses a common root lights hundreds, so the reading ranks verses by how many of the case's roots each carries and keeps the top 12 in canonical order; the coupling trace names only the verses the reading cites. Local, over the full scroll: bereishit 1:1 → itself, Devarim 4:32, Bereishit 2:4 …; devarim 6:4 → itself, Shemot 3:18, Devarim 4:1 …; shabbat roots → Bereishit 2:3, Shemot 20:8, 20:11, 31:13. interpret 15 ms, challenge 10 ms (now finds a kushya for the Shema), resolve 24 ms. Prolog 7 suites green (middot 2.9 s — pairwise scans over the scroll). 5,853 verses loaded, 49,542 root occurrences. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e0eb2f983
commit
861cd4e64e
5 files changed
+6023
-91
No files matched your search
@@ -63,6 +63,11 @@ if [[ "${DOORPOST_SKIP:-0}" != "1" ]]; then
|
|||||||
python3 -I scripts/doorpost_check.py || exit 1
|
python3 -I scripts/doorpost_check.py || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# The engine's verse facts are derived from L1 (scripts/build_engine_verses.py);
|
||||||
|
# an image whose facts lag the scroll reasons over a scroll that is not
|
||||||
|
# the one the pipeline reads. Regenerate and commit, never skip.
|
||||||
|
python3 -I scripts/build_engine_verses.py --check || exit 1
|
||||||
|
|
||||||
if ! docker buildx version >/dev/null 2>&1; then
|
if ! docker buildx version >/dev/null 2>&1; then
|
||||||
echo "ERROR: docker buildx not available — install Docker Desktop or buildx plugin" >&2
|
echo "ERROR: docker buildx not available — install Docker Desktop or buildx plugin" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Executable
+111
@@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""build_engine_verses.py — the Talmudic Engine's verse facts, derived from L1.
|
||||||
|
|
||||||
|
Architecture §3.4: verse(Book, Chapter, Verse, HebrewRoots, Gloss) is "the
|
||||||
|
reasoning layer's view of the specification — not a replacement for L1".
|
||||||
|
Until 2026-10-19 that view was 32 hand-written verses, so any root the
|
||||||
|
engine knew lit the same handful and every reading cited the same list.
|
||||||
|
This script writes talmudic_engine/src/specification/l1_verses.pl from
|
||||||
|
l1/torah — every verse, its roots as the engine names them
|
||||||
|
(Hebrew shoresh → letter names, finals folded: ברא → bet_resh_aleph), the
|
||||||
|
consonantal text as the gloss — and records the SHA-256 of the L1 files it
|
||||||
|
read in the header, so the facts can be checked against the scroll.
|
||||||
|
|
||||||
|
scripts/build_engine_verses.py # write the facts
|
||||||
|
scripts/build_engine_verses.py --check # exit 1 if the facts do not match L1 as it stands
|
||||||
|
|
||||||
|
Devarim 4:2 — nothing added, nothing taken: the engine reads the scroll's
|
||||||
|
roots, not the builder's memory of them.
|
||||||
|
"""
|
||||||
|
import argparse, hashlib, json, os, sys
|
||||||
|
|
||||||
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
L1 = os.path.join(ROOT, "l1", "torah")
|
||||||
|
OUT = os.path.join(ROOT, "talmudic_engine", "src", "specification", "l1_verses.pl")
|
||||||
|
BOOKS = ["bereishit", "shemot", "vayikra", "bamidbar", "devarim"]
|
||||||
|
|
||||||
|
NAMES = {
|
||||||
|
"א": "aleph", "ב": "bet", "ג": "gimel", "ד": "dalet", "ה": "he", "ו": "vav", "ז": "zayin",
|
||||||
|
"ח": "chet", "ט": "tet", "י": "yod", "כ": "kaf", "ך": "kaf", "ל": "lamed", "מ": "mem", "ם": "mem",
|
||||||
|
"נ": "nun", "ן": "nun", "ס": "samekh", "ע": "ayin", "פ": "pe", "ף": "pe", "צ": "tsadi", "ץ": "tsadi",
|
||||||
|
"ק": "qof", "ר": "resh", "ש": "shin", "ת": "tav",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def root_atom(shoresh):
|
||||||
|
if not shoresh:
|
||||||
|
return None
|
||||||
|
names = [NAMES.get(c) for c in shoresh]
|
||||||
|
if not names or any(n is None for n in names):
|
||||||
|
return None
|
||||||
|
return "_".join(names)
|
||||||
|
|
||||||
|
|
||||||
|
def quote(s):
|
||||||
|
return "'" + s.replace("\\", "\\\\").replace("'", "\\'") + "'"
|
||||||
|
|
||||||
|
|
||||||
|
def verse_files():
|
||||||
|
out = []
|
||||||
|
for book in BOOKS:
|
||||||
|
bdir = os.path.join(L1, book)
|
||||||
|
for ch in sorted((d for d in os.listdir(bdir) if d.isdigit()), key=int):
|
||||||
|
cdir = os.path.join(bdir, ch)
|
||||||
|
for f in sorted((f for f in os.listdir(cdir) if f.endswith(".json") and f[:-5].isdigit()), key=lambda x: int(x[:-5])):
|
||||||
|
out.append((book, int(ch), int(f.split(".")[0]), os.path.join(cdir, f)))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def build():
|
||||||
|
h = hashlib.sha256()
|
||||||
|
facts = []
|
||||||
|
nverses = nroots = 0
|
||||||
|
for book, ch, vs, path in verse_files():
|
||||||
|
data = open(path, "rb").read()
|
||||||
|
h.update(f"{book}/{ch}/{vs}\n".encode())
|
||||||
|
h.update(data)
|
||||||
|
d = json.loads(data)
|
||||||
|
roots = []
|
||||||
|
for w in d.get("words", []):
|
||||||
|
a = root_atom(w.get("shoresh"))
|
||||||
|
if a and a not in roots:
|
||||||
|
roots.append(a)
|
||||||
|
gloss = " ".join(w.get("consonants", "") for w in d.get("words", []) if w.get("consonants"))
|
||||||
|
facts.append(f"verse({book}, {ch}, {vs}, [{', '.join(roots)}], {quote(gloss)}).")
|
||||||
|
nverses += 1
|
||||||
|
nroots += len(roots)
|
||||||
|
header = f"""%% l1_verses.pl — GENERATED by scripts/build_engine_verses.py from l1/torah.
|
||||||
|
%% Do not edit: regenerate. verse(Book, Chapter, Verse, Roots, Gloss) for
|
||||||
|
%% every verse of L1; Roots are the engine's letter-name atoms derived from
|
||||||
|
%% each word's shoresh (finals folded), once per verse in word order; Gloss
|
||||||
|
%% is the consonantal text. Included by torah_text.pl.
|
||||||
|
%%
|
||||||
|
%% l1_sha256: {h.hexdigest()}
|
||||||
|
%% verses: {nverses} root_occurrences: {nroots}
|
||||||
|
"""
|
||||||
|
return header + "\n".join(facts) + "\n", h.hexdigest(), nverses
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--check", action="store_true")
|
||||||
|
a = ap.parse_args()
|
||||||
|
text, digest, n = build()
|
||||||
|
if a.check:
|
||||||
|
try:
|
||||||
|
current = open(OUT, encoding="utf-8").read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"engine verses: {OUT} missing — run scripts/build_engine_verses.py", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
if current != text:
|
||||||
|
print(f"engine verses: {OUT} does not match L1 (l1_sha256 now {digest[:12]}…) — regenerate", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"engine verses: match L1 ({n} verses, l1_sha256 {digest[:12]}…)")
|
||||||
|
return
|
||||||
|
with open(OUT, "w", encoding="utf-8") as f:
|
||||||
|
f.write(text)
|
||||||
|
print(f"wrote {OUT}: {n} verses, l1_sha256 {digest[:12]}…")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -111,16 +111,45 @@ find_relevant_mitzvot_traced(case(_Ref, Domain, Roots, _Question), Mitzvot, Coup
|
|||||||
find_relevant_verses(case(Ref, Domain, Roots, Question), Verses) :-
|
find_relevant_verses(case(Ref, Domain, Roots, Question), Verses) :-
|
||||||
find_relevant_verses_traced(case(Ref, Domain, Roots, Question), Verses, _).
|
find_relevant_verses_traced(case(Ref, Domain, Roots, Question), Verses, _).
|
||||||
|
|
||||||
%% Traced version: returns verses AND the coupling trace for each
|
%% Traced version: returns verses AND the coupling trace for each.
|
||||||
|
%%
|
||||||
|
%% Over the whole scroll (2026-10-19, l1_verses.pl) a common root lights
|
||||||
|
%% hundreds of verses; a reading that cites them all cites nothing. The
|
||||||
|
%% verses are ranked by how many of the case's roots they carry — a
|
||||||
|
%% verse sharing three roots stands closer to the case than one sharing
|
||||||
|
%% one — and the reading keeps the top ?MAX_VERSES, ties broken by
|
||||||
|
%% canonical order. The coupling trace is kept only for the verses the
|
||||||
|
%% reading cites: a trace names what the reading stands on.
|
||||||
|
max_verses(12).
|
||||||
|
|
||||||
find_relevant_verses_traced(case(_Ref, _Domain, Roots, _Question), Verses, Couplings) :-
|
find_relevant_verses_traced(case(_Ref, _Domain, Roots, _Question), Verses, Couplings) :-
|
||||||
findall(verse_ref(Book, Ch, Vs, Gloss)-coupled(root(Root), verse(Book, Ch, Vs)),
|
sort(Roots, UniqueRoots),
|
||||||
( member(Root, Roots),
|
findall(Shared-verse_ref(Book, Ch, Vs, Gloss),
|
||||||
verse(Book, Ch, Vs, VerseRoots, Gloss),
|
( verse(Book, Ch, Vs, VerseRoots, Gloss),
|
||||||
|
intersection(UniqueRoots, VerseRoots, SharedRoots),
|
||||||
|
SharedRoots \== [],
|
||||||
|
length(SharedRoots, N),
|
||||||
|
Shared is -N
|
||||||
|
),
|
||||||
|
Scored),
|
||||||
|
%% keysort is stable: equal scores keep the scroll's order
|
||||||
|
keysort(Scored, Ranked),
|
||||||
|
pairs_values(Ranked, RankedVerses),
|
||||||
|
max_verses(Max),
|
||||||
|
take(Max, RankedVerses, Verses),
|
||||||
|
findall(coupled(root(Root), verse(Book, Ch, Vs)),
|
||||||
|
( member(verse_ref(Book, Ch, Vs, _), Verses),
|
||||||
|
verse(Book, Ch, Vs, VerseRoots, _),
|
||||||
|
member(Root, UniqueRoots),
|
||||||
member(Root, VerseRoots)
|
member(Root, VerseRoots)
|
||||||
),
|
),
|
||||||
AllPairs),
|
Couplings).
|
||||||
pairs_keys_values(AllPairs, AllVerses, Couplings),
|
|
||||||
sort(AllVerses, Verses).
|
take(N, List, Prefix) :-
|
||||||
|
length(List, L),
|
||||||
|
( L =< N -> Prefix = List
|
||||||
|
; length(Prefix, N), append(Prefix, _, List)
|
||||||
|
).
|
||||||
|
|
||||||
%% ============================================================
|
%% ============================================================
|
||||||
%% CONSTRUCT INTERPRETATION
|
%% CONSTRUCT INTERPRETATION
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -16,93 +16,19 @@
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
%% ============================================================
|
%% ============================================================
|
||||||
%% BEREISHIT — Creation narratives
|
%% THE SCROLL — every verse of L1, generated (2026-10-19)
|
||||||
%% ============================================================
|
%% ============================================================
|
||||||
|
%%
|
||||||
|
%% The 32 hand-written verses that stood here from Phase 1 are gone:
|
||||||
|
%% with them, any root the engine knew lit the same handful and every
|
||||||
|
%% reading cited the same list. l1_verses.pl is written by
|
||||||
|
%% scripts/build_engine_verses.py from l1/torah — 5,853 verses, each
|
||||||
|
%% word's shoresh as the engine names it, the consonantal text as the
|
||||||
|
%% gloss — and carries the SHA-256 of the L1 it read. Check it against
|
||||||
|
%% the scroll with `scripts/build_engine_verses.py --check`.
|
||||||
|
|
||||||
verse(bereishit, 1, 1, [bet_resh_aleph, bet_resh_aleph, aleph_lamed_he],
|
:- include('l1_verses.pl').
|
||||||
'In the beginning God created the heavens and the earth').
|
|
||||||
verse(bereishit, 1, 3, [aleph_mem_resh, aleph_lamed_he, he_yod_he, aleph_vav_resh],
|
|
||||||
'And God said let there be light and there was light').
|
|
||||||
verse(bereishit, 1, 4, [resh_aleph_he, aleph_lamed_he, aleph_vav_resh, tet_vav_bet, bet_dalet_lamed],
|
|
||||||
'And God saw that the light was good and God separated').
|
|
||||||
verse(bereishit, 1, 27, [bet_resh_aleph, aleph_lamed_he, aleph_dalet_mem, tzade_lamed_mem, bet_resh_aleph],
|
|
||||||
'And God created man in His image in the image of God He created him').
|
|
||||||
verse(bereishit, 2, 2, [kaf_lamed_he, aleph_lamed_he, yod_vav_mem, shin_bet_tav, mem_lamed_aleph_kaf_he],
|
|
||||||
'And on the seventh day God completed His work and He rested').
|
|
||||||
verse(bereishit, 2, 3, [bet_resh_kaf, aleph_lamed_he, yod_vav_mem, shin_bet_tav, qof_dalet_shin],
|
|
||||||
'And God blessed the seventh day and sanctified it').
|
|
||||||
verse(bereishit, 9, 6, [shin_pe_kaf, dalet_mem, aleph_dalet_mem, tzade_lamed_mem, aleph_lamed_he],
|
|
||||||
'Whoever sheds the blood of man by man shall his blood be shed for in the image of God He made man').
|
|
||||||
|
|
||||||
%% ============================================================
|
|
||||||
%% SHEMOT — The ten dibrot and the covenant
|
|
||||||
%% ============================================================
|
|
||||||
|
|
||||||
verse(shemot, 3, 14, [aleph_he_yod_he, aleph_mem_resh, aleph_he_yod_he],
|
|
||||||
'I am that I am').
|
|
||||||
verse(shemot, 20, 2, [aleph_nun_kaf_yod, he_shin_mem, aleph_lamed_he],
|
|
||||||
'I am the LORD your God who brought you out of the land of Egypt').
|
|
||||||
verse(shemot, 20, 3, [he_yod_he, aleph_lamed_he, aleph_chet_resh],
|
|
||||||
'You shall have no other gods before Me').
|
|
||||||
verse(shemot, 20, 8, [zayin_kaf_resh, yod_vav_mem, shin_bet_tav, qof_dalet_shin],
|
|
||||||
'Remember the Sabbath day to sanctify it').
|
|
||||||
verse(shemot, 20, 13, [resh_tzade_chet],
|
|
||||||
'You shall not murder').
|
|
||||||
verse(shemot, 20, 14, [nun_aleph_pe],
|
|
||||||
'You shall not commit adultery').
|
|
||||||
verse(shemot, 20, 15, [gimel_nun_bet],
|
|
||||||
'You shall not steal').
|
|
||||||
verse(shemot, 20, 16, [ayin_nun_he, shin_qof_resh, ayin_dalet],
|
|
||||||
'You shall not bear false witness against your neighbor').
|
|
||||||
verse(shemot, 20, 17, [chet_mem_dalet],
|
|
||||||
'You shall not covet').
|
|
||||||
|
|
||||||
%% ============================================================
|
|
||||||
%% VAYIKRA — Holiness and offerings
|
|
||||||
%% ============================================================
|
|
||||||
|
|
||||||
verse(vayikra, 1, 3, [qof_resh_bet, ayin_lamed_he, tav_mem_yod_mem],
|
|
||||||
'If his offering is a burnt offering let him offer a male without blemish').
|
|
||||||
verse(vayikra, 4, 27, [chet_tet_aleph, nun_pe_shin, shin_gimel_gimel_he],
|
|
||||||
'If anyone of the common people sins unintentionally').
|
|
||||||
verse(vayikra, 19, 2, [qof_dalet_shin, he_yod_he, qof_dalet_shin],
|
|
||||||
'Be holy for I the LORD your God am holy').
|
|
||||||
verse(vayikra, 19, 15, [ayin_shin_he, mem_shin_pe_tet, tzade_dalet_qof],
|
|
||||||
'In righteousness shall you judge your neighbor').
|
|
||||||
verse(vayikra, 19, 18, [aleph_he_bet, resh_ayin, kaf_mem_vav],
|
|
||||||
'You shall love your neighbor as yourself').
|
|
||||||
|
|
||||||
%% ============================================================
|
|
||||||
%% BAMIDBAR — The camp and the cloud
|
|
||||||
%% ============================================================
|
|
||||||
|
|
||||||
verse(bamidbar, 9, 23, [pe_he, he_shin_mem, chet_nun_he, pe_he, he_shin_mem, nun_samekh_ayin],
|
|
||||||
'At the mouth of the LORD they camped and at the mouth of the LORD they journeyed').
|
|
||||||
verse(bamidbar, 10, 2, [ayin_shin_he, shin_nun_yod, chet_tzade_tzade_resh_he, kaf_samekh_pe],
|
|
||||||
'Make two silver trumpets for the calling of the assembly').
|
|
||||||
verse(bamidbar, 35, 11, [mem_qof_lamed_tet, ayin_yod_resh, nun_pe_shin, resh_tzade_chet, shin_gimel_gimel_he],
|
|
||||||
'You shall designate cities of refuge for one who kills a person unintentionally').
|
|
||||||
|
|
||||||
%% ============================================================
|
|
||||||
%% DEVARIM — Moses' final instruction
|
|
||||||
%% ============================================================
|
|
||||||
|
|
||||||
verse(devarim, 6, 4, [shin_mem_ayin, yod_shin_resh_aleph_lamed, he_shin_mem, aleph_lamed_he, he_shin_mem, aleph_chet_dalet],
|
|
||||||
'Hear O Israel the LORD our God the LORD is one').
|
|
||||||
verse(devarim, 6, 5, [aleph_he_bet, he_shin_mem, aleph_lamed_he, kaf_lamed, lamed_bet_bet],
|
|
||||||
'And you shall love the LORD your God with all your heart').
|
|
||||||
verse(devarim, 16, 18, [shin_pe_tet, shin_tet_resh, nun_tav_nun, shin_ayin_resh],
|
|
||||||
'Judges and officers shall you appoint in all your gates').
|
|
||||||
verse(devarim, 16, 20, [tzade_dalet_qof, tzade_dalet_qof, resh_dalet_pe],
|
|
||||||
'Justice justice shall you pursue').
|
|
||||||
verse(devarim, 21, 1, [nun_pe_lamed, chet_lamed_lamed, shin_dalet_he, yod_dalet_ayin],
|
|
||||||
'If a slain person is found in the field and it is not known who struck him').
|
|
||||||
verse(devarim, 25, 12, [nun_tzade_lamed, resh_dalet_pe],
|
|
||||||
'You shall save the pursued from the pursuer').
|
|
||||||
verse(devarim, 26, 2, [lamed_qof_chet, resh_aleph_shin_yod_tav, pe_resh_yod, aleph_dalet_mem_he],
|
|
||||||
'You shall take of the first of all the fruit of the ground').
|
|
||||||
verse(devarim, 26, 5, [aleph_resh_mem_yod, aleph_bet_dalet, aleph_bet_yod],
|
|
||||||
'A wandering Aramean was my father').
|
|
||||||
|
|
||||||
%% ============================================================
|
%% ============================================================
|
||||||
%% QUERIES
|
%% QUERIES
|
||||||
|
|||||||
Reference in new issue
Block a user