diff --git a/l1/README.md b/l1/README.md index 0f5aff7d..628f0c09 100644 --- a/l1/README.md +++ b/l1/README.md @@ -16,7 +16,7 @@ The source is the **Westminster Leningrad Codex (WLC)** — the oldest complete L1 is read-only because Torah is read-only. The specification does not change because the system wishes it would. The cloud cannot be forged because the cloud is the Torah text itself. The system reads. It does not write. It does not negotiate with the Author. -In production, L1 is mounted as a squashfs image (`mount -o ro`) or with filesystem permissions set to 444. No process writes to L1. Ever. +In production, L1 is baked into every image at `/mnt/torah`, owned by root with no write bit (directories 555, files 444): the service user can read it and cannot change it. The pipeline reads and hashes the whole tree at startup and every ten minutes, and will not run a cycle on a scroll that does not match its pinned hash. `scripts/verify_l1.py` does the same reading by hand. No process writes to L1. Ever. ## Contents diff --git a/specs/shorashim_terumah.md b/specs/shorashim_terumah.md index 29e281e5..b71a9e6d 100644 --- a/specs/shorashim_terumah.md +++ b/specs/shorashim_terumah.md @@ -113,17 +113,17 @@ All pinned via lock files per Construction Specification §§1.3-1.5. ### E1. Torah Text (L1) -Source: Westminster Leningrad Codex (WLC) 4.22, cross-validated per Construction Specification §1.2. +Source: Westminster Leningrad Codex (WLC) 4.20, as carried by the Open Scriptures Hebrew Bible (`openscriptures/morphhb`), per Construction Specification §1.2. One source; not cross-validated against a second edition. | Item | Status | Notes | |------|--------|-------| -| Full Torah text — consonantal (ktiv) | ✅ | WLC via Sefaria export + TANACH.us cross-validation. | -| Full Torah text — voweled (nikkud) | ✅ | WLC via Sefaria. | +| Full Torah text — consonantal (ktiv) | ✅ | WLC via OSHB morphhb. | +| Full Torah text — voweled (nikkud) | ✅ | WLC via OSHB morphhb. | | Cantillation marks (raw Unicode codepoints U+0591–U+05AF) | ✅ | Present in WLC data. Stored as raw marks on the text, NOT pre-parsed into trees. The system reads them in the act of reading. | -| Petuchah/Stumah paragraph markers | ✅ | Encoded in WLC/Sefaria data. | -| Ketiv/qere annotations | ✅ | WLC annotations. Stored as `{position, ketiv, qere}` pairs — both readings preserved, never collapsed. | -| Gematria index (root → numerical value → equivalences) | ❌ | Computed once from consonantal text at build time. Letter values fixed. Building equivalence index: ~2-3 days. Verified against independent computation. | -| Smikhut compound index (attested construct-state pairs) | ❌ | Extracted from WLC morphological annotations. Requires Hebrew linguistic knowledge. ~2-3 weeks. | +| Petuchah/Stumah paragraph markers | ⚠️ | Present in the WLC source (OSIS `x-pe` / `x-samekh` milestones). NOT carried into L1: `scripts/build_l1.py` does not read them. | +| Ketiv/qere annotations | ✅ | WLC annotations: 67 pairs in 64 verses. Stored per verse as `{word_position, ketiv, ketiv_consonants, qere, qere_consonants}` — both readings preserved, never collapsed. | +| Gematria (root → numerical value) | ✅ | Not stored in L1: computed from the consonants when read. Letter values fixed. No equivalence index is built. | +| Smikhut compound index (attested construct-state pairs) | ✅ | Built: 9,203 pairs in 4,106 verses, extracted by `scripts/build_l1.py` from the morphology where a word is marked construct. | | L1 SHA-256 hash | ❌ | Computed at build time. Stored in L0 firmware. Verified at every boot. | | Letter counts / word counts / Masoretic notes | ⚠️ | Available in digital WLC. Needs extraction and formatting. | @@ -242,7 +242,7 @@ Updated to reflect corrected architecture. - All programming languages and runtimes (pinned versions) - All infrastructure tools - Nearly all library dependencies -- Torah text (WLC 4.22) with cantillation marks, ketiv/qere, vowels +- Torah text (WLC 4.20, OSHB morphhb) with cantillation marks, ketiv/qere, vowels, lemma and morphology - Talmud and commentary texts (Sefaria) - List of 613 mitzvot with source verses - Root lexicon (BDB roots by Strong's lemma — OSHB Hebrew Lexicon) diff --git a/specs/shorashim_vayakhel.md b/specs/shorashim_vayakhel.md index 809dbe19..c0cd7ca4 100644 --- a/specs/shorashim_vayakhel.md +++ b/specs/shorashim_vayakhel.md @@ -40,24 +40,30 @@ The specification that sits inside the aron must be specified with the same prec | Property | Value | |----------|-------| | **Manuscript tradition** | Leningrad Codex (Codex Leningradensis, Firkovich B 19A) | -| **Digital edition** | Westminster Leningrad Codex (WLC) 4.22 | -| **Source** | Sefaria Export (text, cantillation, vowels) cross-validated against TANACH.us WLC data | -| **Format** | JSON per verse: `{ "ref": "Genesis 1:1", "hebrew": "...", "consonantal": "...", "cantillation": [...], "ketiv_qere": [...] }` | +| **Digital edition** | Westminster Leningrad Codex (WLC) 4.20, as carried by the Open Scriptures Hebrew Bible | +| **Source — text** | `openscriptures/morphhb` at commit `3d15126` (`wlc/Gen.xml` … `Deut.xml`, OSIS XML): the WLC text with vowels and cantillation, and for every word its lemma (Strong's number) and morphology. Text public domain; lemma and morphology CC BY 4.0 | +| **Source — roots** | `openscriptures/HebrewLexicon` at commit `21c9add` (`LexicalIndex.xml`, `AugIndex.xml`): each lemma filed under its Brown-Driver-Briggs root. BDB and Strong's public domain; the index CC BY 4.0 | +| **Builder** | `scripts/build_l1.py`. Deterministic: the same two checkouts give the same bytes and the same hash. Both commits are recorded in `l1/build_report.json` | +| **Extent** | 5 books, 187 chapters, 5,853 verses (WLC/BHS versification; the traditional count is 5,845), 79,982 words | +| **Format** | One JSON file per verse, `l1/torah/{book}/{chapter}/{verse}.json`: `{ "ref": "Bereishit 1:1", "book": "bereishit", "chapter": 1, "verse": 1, "text_hebrew": "...", "words": [...] }`, with `"ketiv_qere": [...]` and `"smikhut": [...]` where the verse has them | +| **Word** | `{ "position": 1, "text": "בְּרֵאשִׁ֖ית", "consonants": "בראשית", "lemma": "7225", "morph": "HR/Ncfsa", "teamim": ["tipcha"], "prefix": "ב", "shoresh": "ראש" }`. `prefix` and `shoresh` are present only where the word has them; `large_letters` marks an enlarged letter (4 words) | | **Integrity** | SHA-256 over every file of the L1 tree (path, then bytes), recorded at build time in `integrity.sha256`. The pipeline re-reads and re-hashes the tree at startup and every ten minutes | -| **Cantillation marks** | Unicode cantillation codepoints (U+0591–U+05AF) preserved as raw marks, NOT pre-parsed | -| **Ketiv/qere** | Derived from WLC ketiv/qere annotations; stored as `{ "position": [book, ch, vs, word], "ketiv": "...", "qere": "..." }` | -| **Gematria index** | Computed once from the consonantal text at build time, stored as lookup table, verified against independent computation | -| **Smikhut compounds** | Extracted from WLC morphological annotations where construct state is marked; stored as attested pairs | +| **Cantillation marks** | Kept on the text as the Unicode codepoints the WLC carries (U+0591–U+05AF), and named per word in `teamim`. The parse tree is NOT pre-computed: the reader builds it from the marks | +| **Ketiv/qere** | From the WLC's ketiv/qere annotations: 67 pairs in 64 verses, stored as `{ "word_position": 6, "ketiv": "...", "ketiv_consonants": "...", "qere": "...", "qere_consonants": "..." }` | +| **Shoresh** | Read from the lexicon by the word's lemma — never derived from the consonants. 57,487 words carry one; 1,378 distinct roots. Particles and pronouns carry none, by rule; names the lexicon gives no etymology carry none | +| **Gematria** | Not stored. Computed from the consonants when read (engine and pipeline) | +| **Petuchah / setumah** | Present in the source as paragraph milestones. Not carried into L1: the builder does not read them | +| **Smikhut compounds** | From the morphology, where a word is marked construct: 9,203 attested pairs in 4,106 verses, stored as `{ "position": 5, "construct": "...", "construct_consonants": "...", "absolute": "...", "absolute_consonants": "..." }` | **Verification procedure:** -1. Download WLC 4.22 from two independent sources (Sefaria, TANACH.us) -2. Compare byte-for-byte — must be identical -3. Extract cantillation, ketiv/qere, and consonantal text -4. Compute SHA-256 of the complete dataset -5. Build squashfs image -6. Mount read-only -7. Verify SHA-256 matches at every system boot -8. Record the hash in L0 (compiled Haskell constant) — the luchot carry the fingerprint of the scroll +1. Check out the two sources at the commits above, beside each other (`~/shorashim-source-data/morphhb`, `…/HebrewLexicon`) +2. Run `scripts/build_l1.py`. It rebuilds `l1/torah/`, `l1/integrity.sha256` and `l1/build_report.json`, and checks the counts: 5 books, 187 chapters, 5,853 verses, cantillation on every verse +3. The SHA-256 it prints must equal the one committed. A different hash means a different scroll: either a source moved or the builder changed, and neither happens silently +4. Record the hash where the vessel is bound to it — `VavPipeline.L1Reader` (the pipeline's pin), `Luchot.Firmware` (L0, the compiled Haskell constant: the luchot carry the fingerprint of the scroll), and the Azazel Processor's goral seed. They move together, in the commit that moves L1 +5. Build the images. L1 is copied into each at `/mnt/torah`, owned by root, with no write bit for anyone +6. At startup and every ten minutes the pipeline reads the scroll and hashes it. `scripts/verify_l1.py` does the same by hand, and is the kohen's first gate + +There is one source for the text, not two: the cross-validation against a second, independent edition that this section once prescribed has not been done. If the scroll does not hash to the pinned value, the system does not serve: no cycle runs and the vessel reports itself not ready. The specification's integrity is verified before the system opens its eyes, and again every ten minutes while they are open. diff --git a/vav_pipeline/lib/vav_pipeline/doorpost.ex b/vav_pipeline/lib/vav_pipeline/doorpost.ex index f83b67be..2e1a126d 100644 --- a/vav_pipeline/lib/vav_pipeline/doorpost.ex +++ b/vav_pipeline/lib/vav_pipeline/doorpost.ex @@ -175,7 +175,7 @@ defmodule VavPipeline.Doorpost do # changes; the update is a deliberate operator commit. A bare # hash-update commit (without a corresponding spec change in the # same commit) is itself a drift signal. - @expected_hash "3f6d47a0b91ce12a1002cfe2d0a6bfe7af4fb280cd05264c87ba914d258a06fe" + @expected_hash "21f1a4d52e21a166be243533f71e7b5be1ab13ac55670a0811ba5b1b4d29fa56" @doc "Return the list of files that constitute the category-grade specification." @spec files() :: [String.t()]