Phase 1-2 build: Steps 5-6, 8-13
Shoresh Engine (Haskell, Step 5) - 12 modules: Types, Lexicon, Binyanim, Teamim, Gematria, Graph, KetivQere, Smikhut, Havdalah, Kriah, KiTov, Firmware - 33 EUnit tests, 0 failures - Firmware module verifies L1 SHA-256 hash at startup Talmudic Engine (SWI-Prolog, Step 6) - 15 modules: halt, reasoning, specification, interface - 57 PlUnit tests, 0 failures - Three cardinal halt conditions: avodah_zarah, shfichut_damim, gilui_arayot Vav Pipeline (Elixir, Steps 8-11) - 14 modules: BereishitCycle, Shema, Cloud, Manna, L1Reader, Specification, HaltConditions, ShabbatTimer, CycleLog, Chatzotzrot, ShoreshEngineClient, TalmudicEngineClient, Application - 46 ExUnit tests, 0 failures - Nishma-first architecture: hears before it speaks Sanhedrin Framework (Erlang/OTP, Step 12) - 8 modules: sanhedrin_app, sanhedrin_sup, escalation, panel_sup, panel, judge, clerk, halt_monitor - 46 EUnit tests, 0 failures (includes fix: rejected outcome now reachable) - Panel sizes: 1/3/23/71 — unanimous capital guilty → acquit (Sanhedrin 17a) - Minority opinions append-only, never deleted Korban Processor (Python, Step 13) - 6 modules: korban, shechitah, semichah, zerikah, haktarah, router Builder tooling: AGENTS.md, opencode.json, memory/, src/tools/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
622e814c9e
commit
80ec364da6
86 files changed
+9646
No files matched your search
Generated
+232
@@ -0,0 +1,232 @@
|
||||
# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
description = "Reusable constraint types to use with typing.Annotated"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
||||
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
description = "Cross-platform colored terminal text."
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
groups = ["dev"]
|
||||
markers = "sys_platform == \"win32\""
|
||||
files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.3.0"
|
||||
description = "brain-dead simple config-ini parsing"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"},
|
||||
{file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "26.0"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"},
|
||||
{file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.6.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"},
|
||||
{file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "tox"]
|
||||
testing = ["coverage", "pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.6.1"
|
||||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pydantic-2.6.1-py3-none-any.whl", hash = "sha256:0b6a909df3192245cb736509a92ff69e4fef76116feffec68e93a567347bae6f"},
|
||||
{file = "pydantic-2.6.1.tar.gz", hash = "sha256:4fd5c182a2488dc63e6d32737ff19937888001e2a6d86e94b3f233104a5d1fa9"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
annotated-types = ">=0.4.0"
|
||||
pydantic-core = "2.16.2"
|
||||
typing-extensions = ">=4.6.1"
|
||||
|
||||
[package.extras]
|
||||
email = ["email-validator (>=2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.16.2"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3fab4e75b8c525a4776e7630b9ee48aea50107fea6ca9f593c98da3f4d11bf7c"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8bde5b48c65b8e807409e6f20baee5d2cd880e0fad00b1a811ebc43e39a00ab2"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2924b89b16420712e9bb8192396026a8fbd6d8726224f918353ac19c4c043d2a"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16aa02e7a0f539098e215fc193c8926c897175d64c7926d00a36188917717a05"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:936a787f83db1f2115ee829dd615c4f684ee48ac4de5779ab4300994d8af325b"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:459d6be6134ce3b38e0ef76f8a672924460c455d45f1ad8fdade36796df1ddc8"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9ee4febb249c591d07b2d4dd36ebcad0ccd128962aaa1801508320896575ef"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40a0bd0bed96dae5712dab2aba7d334a6c67cbcac2ddfca7dbcc4a8176445990"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:870dbfa94de9b8866b37b867a2cb37a60c401d9deb4a9ea392abf11a1f98037b"},
|
||||
{file = "pydantic_core-2.16.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:308974fdf98046db28440eb3377abba274808bf66262e042c412eb2adf852731"},
|
||||
{file = "pydantic_core-2.16.2-cp310-none-win32.whl", hash = "sha256:a477932664d9611d7a0816cc3c0eb1f8856f8a42435488280dfbf4395e141485"},
|
||||
{file = "pydantic_core-2.16.2-cp310-none-win_amd64.whl", hash = "sha256:8f9142a6ed83d90c94a3efd7af8873bf7cefed2d3d44387bf848888482e2d25f"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:406fac1d09edc613020ce9cf3f2ccf1a1b2f57ab00552b4c18e3d5276c67eb11"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce232a6170dd6532096cadbf6185271e4e8c70fc9217ebe105923ac105da9978"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90fec23b4b05a09ad988e7a4f4e081711a90eb2a55b9c984d8b74597599180f"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8aafeedb6597a163a9c9727d8a8bd363a93277701b7bfd2749fbefee2396469e"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9957433c3a1b67bdd4c63717eaf174ebb749510d5ea612cd4e83f2d9142f3fc8"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0d7a9165167269758145756db43a133608a531b1e5bb6a626b9ee24bc38a8f7"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dffaf740fe2e147fedcb6b561353a16243e654f7fe8e701b1b9db148242e1272"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8ed79883b4328b7f0bd142733d99c8e6b22703e908ec63d930b06be3a0e7113"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cf903310a34e14651c9de056fcc12ce090560864d5a2bb0174b971685684e1d8"},
|
||||
{file = "pydantic_core-2.16.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:46b0d5520dbcafea9a8645a8164658777686c5c524d381d983317d29687cce97"},
|
||||
{file = "pydantic_core-2.16.2-cp311-none-win32.whl", hash = "sha256:70651ff6e663428cea902dac297066d5c6e5423fda345a4ca62430575364d62b"},
|
||||
{file = "pydantic_core-2.16.2-cp311-none-win_amd64.whl", hash = "sha256:98dc6f4f2095fc7ad277782a7c2c88296badcad92316b5a6e530930b1d475ebc"},
|
||||
{file = "pydantic_core-2.16.2-cp311-none-win_arm64.whl", hash = "sha256:ef6113cd31411eaf9b39fc5a8848e71c72656fd418882488598758b2c8c6dfa0"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:88646cae28eb1dd5cd1e09605680c2b043b64d7481cdad7f5003ebef401a3039"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7b883af50eaa6bb3299780651e5be921e88050ccf00e3e583b1e92020333304b"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bf26c2e2ea59d32807081ad51968133af3025c4ba5753e6a794683d2c91bf6e"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99af961d72ac731aae2a1b55ccbdae0733d816f8bfb97b41909e143de735f522"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02906e7306cb8c5901a1feb61f9ab5e5c690dbbeaa04d84c1b9ae2a01ebe9379"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5362d099c244a2d2f9659fb3c9db7c735f0004765bbe06b99be69fbd87c3f15"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ac426704840877a285d03a445e162eb258924f014e2f074e209d9b4ff7bf380"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b94cbda27267423411c928208e89adddf2ea5dd5f74b9528513f0358bba019cb"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6db58c22ac6c81aeac33912fb1af0e930bc9774166cdd56eade913d5f2fff35e"},
|
||||
{file = "pydantic_core-2.16.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396fdf88b1b503c9c59c84a08b6833ec0c3b5ad1a83230252a9e17b7dfb4cffc"},
|
||||
{file = "pydantic_core-2.16.2-cp312-none-win32.whl", hash = "sha256:7c31669e0c8cc68400ef0c730c3a1e11317ba76b892deeefaf52dcb41d56ed5d"},
|
||||
{file = "pydantic_core-2.16.2-cp312-none-win_amd64.whl", hash = "sha256:a3b7352b48fbc8b446b75f3069124e87f599d25afb8baa96a550256c031bb890"},
|
||||
{file = "pydantic_core-2.16.2-cp312-none-win_arm64.whl", hash = "sha256:a9e523474998fb33f7c1a4d55f5504c908d57add624599e095c20fa575b8d943"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ae34418b6b389d601b31153b84dce480351a352e0bb763684a1b993d6be30f17"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:732bd062c9e5d9582a30e8751461c1917dd1ccbdd6cafb032f02c86b20d2e7ec"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b52776a2e3230f4854907a1e0946eec04d41b1fc64069ee774876bbe0eab55"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef551c053692b1e39e3f7950ce2296536728871110e7d75c4e7753fb30ca87f4"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ebb892ed8599b23fa8f1799e13a12c87a97a6c9d0f497525ce9858564c4575a4"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa6c8c582036275997a733427b88031a32ffa5dfc3124dc25a730658c47a572f"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ba0884a91f1aecce75202473ab138724aa4fb26d7707f2e1fa6c3e68c84fbf"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7924e54f7ce5d253d6160090ddc6df25ed2feea25bfb3339b424a9dd591688bc"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69a7b96b59322a81c2203be537957313b07dd333105b73db0b69212c7d867b4b"},
|
||||
{file = "pydantic_core-2.16.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7e6231aa5bdacda78e96ad7b07d0c312f34ba35d717115f4b4bff6cb87224f0f"},
|
||||
{file = "pydantic_core-2.16.2-cp38-none-win32.whl", hash = "sha256:41dac3b9fce187a25c6253ec79a3f9e2a7e761eb08690e90415069ea4a68ff7a"},
|
||||
{file = "pydantic_core-2.16.2-cp38-none-win_amd64.whl", hash = "sha256:f685dbc1fdadb1dcd5b5e51e0a378d4685a891b2ddaf8e2bba89bd3a7144e44a"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:55749f745ebf154c0d63d46c8c58594d8894b161928aa41adbb0709c1fe78b77"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b30b0dd58a4509c3bd7eefddf6338565c4905406aee0c6e4a5293841411a1286"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18de31781cdc7e7b28678df7c2d7882f9692ad060bc6ee3c94eb15a5d733f8f7"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5864b0242f74b9dd0b78fd39db1768bc3f00d1ffc14e596fd3e3f2ce43436a33"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8f9186ca45aee030dc8234118b9c0784ad91a0bb27fc4e7d9d6608a5e3d386c"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc6f6c9be0ab6da37bc77c2dda5f14b1d532d5dbef00311ee6e13357a418e646"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa057095f621dad24a1e906747179a69780ef45cc8f69e97463692adbcdae878"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ad84731a26bcfb299f9eab56c7932d46f9cad51c52768cace09e92a19e4cf55"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3b052c753c4babf2d1edc034c97851f867c87d6f3ea63a12e2700f159f5c41c3"},
|
||||
{file = "pydantic_core-2.16.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e0f686549e32ccdb02ae6f25eee40cc33900910085de6aa3790effd391ae10c2"},
|
||||
{file = "pydantic_core-2.16.2-cp39-none-win32.whl", hash = "sha256:7afb844041e707ac9ad9acad2188a90bffce2c770e6dc2318be0c9916aef1469"},
|
||||
{file = "pydantic_core-2.16.2-cp39-none-win_amd64.whl", hash = "sha256:9da90d393a8227d717c19f5397688a38635afec89f2e2d7af0df037f3249c39a"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f60f920691a620b03082692c378661947d09415743e437a7478c309eb0e4f82"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:47924039e785a04d4a4fa49455e51b4eb3422d6eaacfde9fc9abf8fdef164e8a"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6294e76b0380bb7a61eb8a39273c40b20beb35e8c87ee101062834ced19c545"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe56851c3f1d6f5384b3051c536cc81b3a93a73faf931f404fef95217cf1e10d"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d776d30cde7e541b8180103c3f294ef7c1862fd45d81738d156d00551005784"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:72f7919af5de5ecfaf1eba47bf9a5d8aa089a3340277276e5636d16ee97614d7"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4bfcbde6e06c56b30668a0c872d75a7ef3025dc3c1823a13cf29a0e9b33f67e8"},
|
||||
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ff7c97eb7a29aba230389a2661edf2e9e06ce616c7e35aa764879b6894a44b25"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9b5f13857da99325dcabe1cc4e9e6a3d7b2e2c726248ba5dd4be3e8e4a0b6d0e"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a7e41e3ada4cca5f22b478c08e973c930e5e6c7ba3588fb8e35f2398cdcc1545"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60eb8ceaa40a41540b9acae6ae7c1f0a67d233c40dc4359c256ad2ad85bdf5e5"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7beec26729d496a12fd23cf8da9944ee338c8b8a17035a560b585c36fe81af20"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22c5f022799f3cd6741e24f0443ead92ef42be93ffda0d29b2597208c94c3753"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:eca58e319f4fd6df004762419612122b2c7e7d95ffafc37e890252f869f3fb2a"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed957db4c33bc99895f3a1672eca7e80e8cda8bd1e29a80536b4ec2153fa9804"},
|
||||
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:459c0d338cc55d099798618f714b21b7ece17eb1a87879f2da20a3ff4c7628e2"},
|
||||
{file = "pydantic_core-2.16.2.tar.gz", hash = "sha256:0ba503850d8b8dcc18391f10de896ae51d37fe5fe43dbfb6a35c5c5cad271a06"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.19.2"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"},
|
||||
{file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
windows-terminal = ["colorama (>=0.4.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.4.2"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"},
|
||||
{file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = ">=1"
|
||||
packaging = ">=20"
|
||||
pluggy = ">=1.5,<2"
|
||||
pygments = ">=2.7.2"
|
||||
|
||||
[package.extras]
|
||||
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.9+"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
|
||||
{file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
|
||||
]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "==3.12.2"
|
||||
content-hash = "05edb007ce5b000462960d9caaa0110ef611d4ffc74e97b38fcec20a3004b754"
|
||||
@@ -0,0 +1,23 @@
|
||||
[project]
|
||||
name = "korban-processor"
|
||||
version = "0.1.0"
|
||||
description = "Korban Processor — input processing following the offering protocol"
|
||||
authors = [
|
||||
{name = "Bezalel"}
|
||||
]
|
||||
requires-python = "==3.12.2"
|
||||
dependencies = [
|
||||
"pydantic==2.6.1",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.0,<9.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["test"]
|
||||
@@ -0,0 +1,43 @@
|
||||
"""
|
||||
Korban Processor — Input processing following the offering protocol.
|
||||
|
||||
Architecture §3.5:
|
||||
Accepts model outputs (the korbanot), processes them through the offering
|
||||
protocol, extracts symbolic content, transforms into Prolog-compatible
|
||||
format for the Talmudic Engine.
|
||||
|
||||
The offering protocol:
|
||||
semichah → tag provenance
|
||||
shechitah → terminate raw form
|
||||
zerikah → extract vital content
|
||||
haktarah → transform modality (prose → logical propositions)
|
||||
route → send to appropriate system component
|
||||
|
||||
Phase 2 (Step 13): at least shechitah and zerikah.
|
||||
"""
|
||||
|
||||
from korban_processor.korban import (
|
||||
Korban,
|
||||
ProcessedKorban,
|
||||
OfferingType,
|
||||
Provenance,
|
||||
process_korban,
|
||||
)
|
||||
from korban_processor.semichah import semichah
|
||||
from korban_processor.shechitah import shechitah
|
||||
from korban_processor.zerikah import zerikah
|
||||
from korban_processor.haktarah import haktarah
|
||||
from korban_processor.router import route
|
||||
|
||||
__all__ = [
|
||||
"Korban",
|
||||
"ProcessedKorban",
|
||||
"OfferingType",
|
||||
"Provenance",
|
||||
"process_korban",
|
||||
"semichah",
|
||||
"shechitah",
|
||||
"zerikah",
|
||||
"haktarah",
|
||||
"route",
|
||||
]
|
||||
@@ -0,0 +1,199 @@
|
||||
"""
|
||||
Haktarah — transform modality (prose → Prolog propositions).
|
||||
|
||||
Architecture §3.5:
|
||||
Convert prose insights to Prolog-compatible format
|
||||
for the Talmudic Engine.
|
||||
|
||||
The haktarah (burning on the altar) transforms the physical
|
||||
into the ethereal — prose into logic, natural language into
|
||||
formal propositions.
|
||||
|
||||
Phase 2: Pattern-based extraction of structured facts.
|
||||
Phase 3: Will use NLP + Talmudic Engine for deeper transformation.
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
from korban_processor.zerikah import (
|
||||
extract_torah_references,
|
||||
extract_hebrew_words,
|
||||
extract_roots,
|
||||
)
|
||||
|
||||
|
||||
def haktarah(vital_content: str) -> List[str]:
|
||||
"""
|
||||
Transform vital content into Prolog-compatible propositions.
|
||||
|
||||
Each proposition is a Prolog-format string that the Talmudic Engine
|
||||
can parse and reason about.
|
||||
|
||||
Args:
|
||||
vital_content: Extracted vital content from zerikah
|
||||
|
||||
Returns:
|
||||
List of Prolog-format proposition strings
|
||||
"""
|
||||
if not vital_content.strip():
|
||||
return []
|
||||
|
||||
propositions: List[str] = []
|
||||
|
||||
# 1. Extract Torah references as verse/3 facts
|
||||
refs = extract_torah_references(vital_content)
|
||||
for ref in refs:
|
||||
prolog_ref = torah_ref_to_prolog(ref)
|
||||
if prolog_ref:
|
||||
propositions.append(prolog_ref)
|
||||
|
||||
# 2. Extract Hebrew roots as root/2 facts
|
||||
roots = extract_roots(vital_content)
|
||||
for root in roots:
|
||||
prolog_root = root_to_prolog(root)
|
||||
if prolog_root:
|
||||
propositions.append(prolog_root)
|
||||
|
||||
# 3. Extract analytical claims as claim/2 facts
|
||||
claims = extract_claims(vital_content)
|
||||
for claim in claims:
|
||||
propositions.append(claim)
|
||||
|
||||
# 4. Extract connections between roots as connection/3 facts
|
||||
connections = extract_connections(vital_content)
|
||||
for conn in connections:
|
||||
propositions.append(conn)
|
||||
|
||||
return propositions
|
||||
|
||||
|
||||
# --- Book name normalization ---
|
||||
|
||||
_BOOK_MAP = {
|
||||
"genesis": "bereishit",
|
||||
"gen": "bereishit",
|
||||
"bereishit": "bereishit",
|
||||
"exodus": "shemot",
|
||||
"exod": "shemot",
|
||||
"exo": "shemot",
|
||||
"shemot": "shemot",
|
||||
"leviticus": "vayikra",
|
||||
"lev": "vayikra",
|
||||
"vayikra": "vayikra",
|
||||
"numbers": "bamidbar",
|
||||
"num": "bamidbar",
|
||||
"bamidbar": "bamidbar",
|
||||
"deuteronomy": "devarim",
|
||||
"deut": "devarim",
|
||||
"devarim": "devarim",
|
||||
}
|
||||
|
||||
|
||||
def torah_ref_to_prolog(ref_str: str) -> str:
|
||||
"""Convert a Torah reference string to a Prolog verse/3 fact."""
|
||||
# Match "Book Chapter:Verse"
|
||||
match = re.match(
|
||||
r"([A-Za-z]+)\.?\s+(\d+):(\d+)",
|
||||
ref_str,
|
||||
)
|
||||
if match:
|
||||
book_raw = match.group(1).lower().rstrip(".")
|
||||
chapter = match.group(2)
|
||||
verse = match.group(3)
|
||||
book = _BOOK_MAP.get(book_raw, book_raw)
|
||||
return f"verse({book}, {chapter}, {verse})"
|
||||
return ""
|
||||
|
||||
|
||||
def root_to_prolog(root_str: str) -> str:
|
||||
"""Convert a root notation to a Prolog root/2 fact."""
|
||||
# Hebrew root: א-ב-ג or א.ב.ג
|
||||
match = re.match(
|
||||
r"([\u05D0-\u05EA])[-.]"
|
||||
r"([\u05D0-\u05EA])[-.]"
|
||||
r"([\u05D0-\u05EA])",
|
||||
root_str,
|
||||
)
|
||||
if match:
|
||||
c1, c2, c3 = match.group(1), match.group(2), match.group(3)
|
||||
return f'root("{c1}{c2}{c3}", hebrew)'
|
||||
|
||||
# "root XYZ" or "shoresh XYZ" with Hebrew consonants
|
||||
match = re.match(
|
||||
r"(?:root|shoresh)\s+([\u05D0-\u05EA]{2,3})",
|
||||
root_str,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
if match:
|
||||
consonants = match.group(1)
|
||||
return f'root("{consonants}", hebrew)'
|
||||
|
||||
# Transliterated root
|
||||
match = re.match(
|
||||
r"(?:root|shoresh)\s+([a-z]{3,})",
|
||||
root_str,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
if match:
|
||||
letters = match.group(1)
|
||||
return f"root({letters}, transliterated)"
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def extract_claims(vital_content: str) -> List[str]:
|
||||
"""
|
||||
Extract analytical claims as Prolog claim/2 facts.
|
||||
|
||||
Looks for sentences with "means", "indicates", "signifies", etc.
|
||||
"""
|
||||
claims = []
|
||||
sentences = re.split(r"(?<=[.!?])\s+", vital_content)
|
||||
|
||||
claim_pattern = re.compile(
|
||||
r"(.+?)\s+(?:means?|indicates?|signifies?|represents?)\s+(.+?)(?:\.|$)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
for sentence in sentences:
|
||||
match = claim_pattern.search(sentence)
|
||||
if match:
|
||||
subject = sanitize_prolog_string(match.group(1).strip())
|
||||
predicate = sanitize_prolog_string(match.group(2).strip())
|
||||
if subject and predicate:
|
||||
claims.append(f'claim("{subject}", "{predicate}")')
|
||||
|
||||
return claims
|
||||
|
||||
|
||||
def extract_connections(vital_content: str) -> List[str]:
|
||||
"""
|
||||
Extract connections between concepts as Prolog connection/3 facts.
|
||||
|
||||
Looks for "X connects to Y", "X is related to Y", etc.
|
||||
"""
|
||||
connections = []
|
||||
|
||||
conn_pattern = re.compile(
|
||||
r"(.+?)\s+(?:connects?\s+to|is\s+related\s+to|parallels?|echoes?)\s+(.+?)(?:\.|$)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
for match in conn_pattern.finditer(vital_content):
|
||||
a = sanitize_prolog_string(match.group(1).strip())
|
||||
b = sanitize_prolog_string(match.group(2).strip())
|
||||
if a and b:
|
||||
connections.append(f'connection("{a}", "{b}", semantic)')
|
||||
|
||||
return connections
|
||||
|
||||
|
||||
def sanitize_prolog_string(s: str) -> str:
|
||||
"""Sanitize a string for use in a Prolog term — escape quotes, limit length."""
|
||||
s = s.replace('"', '\\"')
|
||||
s = s.replace("\n", " ")
|
||||
# Limit length for Prolog term readability
|
||||
if len(s) > 200:
|
||||
s = s[:200] + "..."
|
||||
return s
|
||||
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Core offering protocol and data types.
|
||||
|
||||
Architecture §3.5: Korban Processor.
|
||||
Construction spec §1.4: pydantic 2.6.1 for data validation.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class OfferingType(Enum):
|
||||
"""Types of korbanot — each determines routing."""
|
||||
OLAH = "olah" # Total consumption — fully absorbed by system
|
||||
SHELAMIM = "shelamim" # Shared — partial return to source
|
||||
CHATAT = "chatat" # Error correction
|
||||
MINCHAH = "minchah" # Minimal input
|
||||
|
||||
|
||||
class Provenance(Enum):
|
||||
"""Source of the korban — who brought it."""
|
||||
CLAUDE = "claude"
|
||||
MISTRAL = "mistral"
|
||||
GPT = "gpt"
|
||||
LLAMA = "llama"
|
||||
GEMMA = "gemma"
|
||||
HUMAN = "human"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Korban:
|
||||
"""A raw offering before processing."""
|
||||
raw_content: str
|
||||
provenance: Provenance
|
||||
offering_type: OfferingType
|
||||
source_query: str # what prompted this output
|
||||
|
||||
|
||||
@dataclass
|
||||
class ProcessedKorban:
|
||||
"""A processed offering — vital content extracted, propositions generated."""
|
||||
vital_content: str # extracted essence
|
||||
propositions: List[str] # Prolog-format logical statements
|
||||
provenance: Provenance
|
||||
offering_type: OfferingType
|
||||
discarded: List[str] = field(default_factory=list) # what was stripped
|
||||
source_query: str = ""
|
||||
|
||||
|
||||
def process_korban(
|
||||
content: str,
|
||||
source: Provenance,
|
||||
query: str,
|
||||
offering_type: OfferingType = OfferingType.OLAH,
|
||||
) -> ProcessedKorban:
|
||||
"""
|
||||
Full offering protocol.
|
||||
|
||||
semichah → tag provenance
|
||||
shechitah → terminate raw form
|
||||
zerikah → extract vital content
|
||||
haktarah → transform modality
|
||||
route → send to appropriate component
|
||||
"""
|
||||
from korban_processor.semichah import semichah
|
||||
from korban_processor.shechitah import shechitah
|
||||
from korban_processor.zerikah import zerikah
|
||||
from korban_processor.haktarah import haktarah
|
||||
from korban_processor.router import route
|
||||
|
||||
# 1. Semichah — tag provenance
|
||||
korban = semichah(content, source, query, offering_type)
|
||||
|
||||
# 2. Shechitah — terminate raw form
|
||||
terminated = shechitah(korban)
|
||||
|
||||
# 3. Zerikah — extract vital content
|
||||
vital, discarded = zerikah(terminated, korban)
|
||||
|
||||
# 4. Haktarah — transform to propositions
|
||||
propositions = haktarah(vital)
|
||||
|
||||
processed = ProcessedKorban(
|
||||
vital_content=vital,
|
||||
propositions=propositions,
|
||||
provenance=source,
|
||||
offering_type=offering_type,
|
||||
discarded=discarded,
|
||||
source_query=query,
|
||||
)
|
||||
|
||||
# 5. Route — send to appropriate component
|
||||
route(processed, offering_type)
|
||||
|
||||
return processed
|
||||
@@ -0,0 +1,130 @@
|
||||
"""
|
||||
Router — output routing based on offering type.
|
||||
|
||||
Architecture §3.5:
|
||||
Route to appropriate component based on offering type.
|
||||
|
||||
OLAH → total consumption — all goes to Talmudic Engine
|
||||
SHELAMIM → shared — some to engine, some returned to source context
|
||||
CHATAT → error correction — route to correction subsystem
|
||||
MINCHAH → minimal — lightweight processing
|
||||
|
||||
Phase 2: Routing is logged but not executed (engines not connected).
|
||||
Phase 3 (Step 14): Real routing to Talmudic Engine via socket,
|
||||
to Sanhedrin via BEAM distribution.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
from korban_processor.korban import ProcessedKorban, OfferingType
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RoutingResult:
|
||||
"""Record of where a processed korban was routed."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
destination: str,
|
||||
propositions_sent: int,
|
||||
returned_to_source: bool = False,
|
||||
):
|
||||
self.destination = destination
|
||||
self.propositions_sent = propositions_sent
|
||||
self.returned_to_source = returned_to_source
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"RoutingResult(dest={self.destination}, "
|
||||
f"sent={self.propositions_sent}, "
|
||||
f"returned={self.returned_to_source})"
|
||||
)
|
||||
|
||||
|
||||
# Module-level routing log for inspection/testing
|
||||
_routing_log: List[RoutingResult] = []
|
||||
|
||||
|
||||
def route(processed: ProcessedKorban, offering_type: OfferingType) -> RoutingResult:
|
||||
"""
|
||||
Route processed korban to appropriate component.
|
||||
|
||||
Phase 2: Logs the routing decision but does not execute.
|
||||
Phase 3: Sends propositions to Talmudic Engine, etc.
|
||||
"""
|
||||
n_props = len(processed.propositions)
|
||||
|
||||
if offering_type == OfferingType.OLAH:
|
||||
# Total consumption — all goes to Talmudic Engine
|
||||
result = RoutingResult(
|
||||
destination="talmudic_engine",
|
||||
propositions_sent=n_props,
|
||||
returned_to_source=False,
|
||||
)
|
||||
logger.info(
|
||||
"OLAH: %d propositions routed to talmudic_engine (provenance: %s)",
|
||||
n_props,
|
||||
processed.provenance.value,
|
||||
)
|
||||
|
||||
elif offering_type == OfferingType.SHELAMIM:
|
||||
# Shared — some to engine, some returned to source
|
||||
result = RoutingResult(
|
||||
destination="talmudic_engine",
|
||||
propositions_sent=n_props,
|
||||
returned_to_source=True,
|
||||
)
|
||||
logger.info(
|
||||
"SHELAMIM: %d propositions routed to talmudic_engine + return to source (provenance: %s)",
|
||||
n_props,
|
||||
processed.provenance.value,
|
||||
)
|
||||
|
||||
elif offering_type == OfferingType.CHATAT:
|
||||
# Error correction — route to correction subsystem
|
||||
result = RoutingResult(
|
||||
destination="error_correction",
|
||||
propositions_sent=n_props,
|
||||
returned_to_source=False,
|
||||
)
|
||||
logger.info(
|
||||
"CHATAT: %d propositions routed to error_correction (provenance: %s)",
|
||||
n_props,
|
||||
processed.provenance.value,
|
||||
)
|
||||
|
||||
elif offering_type == OfferingType.MINCHAH:
|
||||
# Minimal — lightweight processing
|
||||
result = RoutingResult(
|
||||
destination="talmudic_engine",
|
||||
propositions_sent=n_props,
|
||||
returned_to_source=False,
|
||||
)
|
||||
logger.info(
|
||||
"MINCHAH: %d propositions routed to talmudic_engine (provenance: %s)",
|
||||
n_props,
|
||||
processed.provenance.value,
|
||||
)
|
||||
|
||||
else:
|
||||
result = RoutingResult(
|
||||
destination="unknown",
|
||||
propositions_sent=0,
|
||||
returned_to_source=False,
|
||||
)
|
||||
logger.warning("Unknown offering type: %s", offering_type)
|
||||
|
||||
_routing_log.append(result)
|
||||
return result
|
||||
|
||||
|
||||
def get_routing_log() -> List[RoutingResult]:
|
||||
"""Get the routing log (for testing/inspection)."""
|
||||
return list(_routing_log)
|
||||
|
||||
|
||||
def clear_routing_log() -> None:
|
||||
"""Clear the routing log."""
|
||||
_routing_log.clear()
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Semichah — provenance tagging.
|
||||
|
||||
Architecture §3.5:
|
||||
Tag provenance — associate input with its source.
|
||||
|
||||
The semichah (laying of hands) identifies who brought the offering.
|
||||
Every korban must have known provenance. Anonymous input is rejected.
|
||||
"""
|
||||
|
||||
from korban_processor.korban import Korban, OfferingType, Provenance
|
||||
|
||||
|
||||
def semichah(
|
||||
content: str,
|
||||
source: Provenance,
|
||||
query: str,
|
||||
offering_type: OfferingType = OfferingType.OLAH,
|
||||
) -> Korban:
|
||||
"""
|
||||
Tag provenance — associate input with its source.
|
||||
|
||||
Args:
|
||||
content: Raw model output or human input
|
||||
source: Who produced this content
|
||||
query: What prompted this output
|
||||
offering_type: What kind of offering this is
|
||||
|
||||
Returns:
|
||||
A Korban with provenance attached
|
||||
|
||||
Raises:
|
||||
ValueError: If content is empty or source is invalid
|
||||
"""
|
||||
if not content or not content.strip():
|
||||
raise ValueError("Empty korban — nothing to offer")
|
||||
|
||||
if not isinstance(source, Provenance):
|
||||
raise ValueError(f"Unknown provenance: {source}")
|
||||
|
||||
return Korban(
|
||||
raw_content=content,
|
||||
provenance=source,
|
||||
offering_type=offering_type,
|
||||
source_query=query,
|
||||
)
|
||||
@@ -0,0 +1,157 @@
|
||||
"""
|
||||
Shechitah — terminate raw form.
|
||||
|
||||
Architecture §3.5:
|
||||
Strip assistant voice, formatting, preamble.
|
||||
|
||||
Architecture §8.2 (Avodah Zarah Firewall):
|
||||
The shechitah step is the FIRST line of defense.
|
||||
It terminates the raw form — the model's voice, its formatting
|
||||
conventions, its self-referential hedging. What remains is content
|
||||
stripped of personality.
|
||||
|
||||
The model is not a teacher. It is a korban source.
|
||||
The content is not Torah. It is raw material.
|
||||
"""
|
||||
|
||||
import re
|
||||
from korban_processor.korban import Korban
|
||||
|
||||
|
||||
# --- Patterns to strip ---
|
||||
|
||||
# Assistant preambles — the self-important throat-clearing
|
||||
_PREAMBLE_PATTERNS = [
|
||||
re.compile(r"^(Great|Excellent|Good|Wonderful|Interesting|Fascinating)\s+(question|point|observation)[.!]\s*", re.IGNORECASE),
|
||||
re.compile(r"^(Sure|Certainly|Of course|Absolutely|Happy to help)[,!.]?\s*(I('d| would| can| will)?\s+(be happy to|help|explain|analyze|provide|break down).*?[.!]\s*)?", re.IGNORECASE),
|
||||
re.compile(r"^(Thank you for|Thanks for)\s+(asking|sharing|your|the).*?[.!]\s*", re.IGNORECASE),
|
||||
re.compile(r"^Let me (help|explain|analyze|break down|walk you through).*?[.!:]\s*", re.IGNORECASE),
|
||||
re.compile(r"^I('d| would) (be happy|love|like) to.*?[.!:]\s*", re.IGNORECASE),
|
||||
re.compile(r"^Here('s| is) (a |an |my |the )?(summary|breakdown|analysis|explanation|overview).*?[.:]\s*", re.IGNORECASE),
|
||||
]
|
||||
|
||||
# Self-reference — the model talking about itself
|
||||
_SELF_REFERENCE_PATTERNS = [
|
||||
re.compile(r"As an AI( language model| assistant)?,?\s*", re.IGNORECASE),
|
||||
re.compile(r"As a (large )?language model,?\s*", re.IGNORECASE),
|
||||
re.compile(r"I('m| am) (just )?an AI.*?[.,]\s*", re.IGNORECASE),
|
||||
re.compile(r"My (training|knowledge|understanding) (data |cutoff )?.*?[.,]\s*", re.IGNORECASE),
|
||||
re.compile(r"I don't have (personal )?(opinions?|feelings?|beliefs?).*?[.,]\s*", re.IGNORECASE),
|
||||
re.compile(r"I should (note|mention|point out|clarify) that.*?[.,]\s*", re.IGNORECASE),
|
||||
]
|
||||
|
||||
# Hedging — the cautious filler
|
||||
_HEDGING_PATTERNS = [
|
||||
re.compile(r"It('s| is) worth (noting|mentioning|pointing out) that\s*", re.IGNORECASE),
|
||||
re.compile(r"It('s| is) important to (note|remember|keep in mind) that\s*", re.IGNORECASE),
|
||||
re.compile(r"(However|That said|With that said|That being said),?\s+it('s| is) (also )?(important|worth|notable).*?that\s*", re.IGNORECASE),
|
||||
re.compile(r"(Of course|Naturally|Obviously|Clearly),?\s*", re.IGNORECASE),
|
||||
re.compile(r"In (my|this) (opinion|view|analysis|understanding),?\s*", re.IGNORECASE),
|
||||
]
|
||||
|
||||
# Markdown formatting
|
||||
_MARKDOWN_PATTERNS = [
|
||||
re.compile(r"^#{1,6}\s+", re.MULTILINE), # Headers
|
||||
re.compile(r"\*\*(.+?)\*\*"), # Bold
|
||||
re.compile(r"\*(.+?)\*"), # Italic
|
||||
re.compile(r"^[-*+]\s+", re.MULTILINE), # Bullet points → keep content
|
||||
re.compile(r"^\d+\.\s+", re.MULTILINE), # Numbered lists → keep content
|
||||
re.compile(r"```[\s\S]*?```"), # Code blocks
|
||||
re.compile(r"`([^`]+)`"), # Inline code
|
||||
]
|
||||
|
||||
# Closing filler
|
||||
_CLOSING_PATTERNS = [
|
||||
re.compile(r"\n+(Let me know|Feel free|Don't hesitate|I hope|Hope this|If you have|Would you like).*$", re.IGNORECASE | re.DOTALL),
|
||||
re.compile(r"\n+(Is there anything else|Do you want me to|Shall I|Want me to).*$", re.IGNORECASE | re.DOTALL),
|
||||
]
|
||||
|
||||
|
||||
def shechitah(korban: Korban) -> str:
|
||||
"""
|
||||
Terminate raw form — strip assistant voice, formatting, preamble.
|
||||
|
||||
The shechitah must be swift and complete. What remains is
|
||||
content without personality, prose without performance.
|
||||
|
||||
Args:
|
||||
korban: The tagged offering
|
||||
|
||||
Returns:
|
||||
Terminated content string
|
||||
"""
|
||||
content = korban.raw_content
|
||||
|
||||
# 1. Strip preambles
|
||||
content = strip_preamble(content)
|
||||
|
||||
# 2. Strip self-reference
|
||||
content = strip_self_reference(content)
|
||||
|
||||
# 3. Strip hedging
|
||||
content = strip_hedging(content)
|
||||
|
||||
# 4. Strip markdown formatting (preserve text content)
|
||||
content = strip_markdown(content)
|
||||
|
||||
# 5. Strip closing filler
|
||||
content = strip_closing(content)
|
||||
|
||||
# 6. Clean up whitespace
|
||||
content = clean_whitespace(content)
|
||||
|
||||
return content
|
||||
|
||||
|
||||
def strip_preamble(content: str) -> str:
|
||||
"""Strip assistant preambles from the beginning of content."""
|
||||
for pattern in _PREAMBLE_PATTERNS:
|
||||
content = pattern.sub("", content, count=1)
|
||||
return content
|
||||
|
||||
|
||||
def strip_self_reference(content: str) -> str:
|
||||
"""Strip model self-reference throughout content."""
|
||||
for pattern in _SELF_REFERENCE_PATTERNS:
|
||||
content = pattern.sub("", content)
|
||||
return content
|
||||
|
||||
|
||||
def strip_hedging(content: str) -> str:
|
||||
"""Strip cautious hedging phrases."""
|
||||
for pattern in _HEDGING_PATTERNS:
|
||||
content = pattern.sub("", content)
|
||||
return content
|
||||
|
||||
|
||||
def strip_markdown(content: str) -> str:
|
||||
"""Strip markdown formatting, preserving text content."""
|
||||
# Remove code blocks entirely (they are formatting, not Torah content)
|
||||
content = re.sub(r"```[\s\S]*?```", "", content)
|
||||
# Remove inline code markers but keep the text
|
||||
content = re.sub(r"`([^`]+)`", r"\1", content)
|
||||
# Remove headers markers but keep text
|
||||
content = re.sub(r"^#{1,6}\s+", "", content, flags=re.MULTILINE)
|
||||
# Remove bold/italic markers but keep text
|
||||
content = re.sub(r"\*\*(.+?)\*\*", r"\1", content)
|
||||
content = re.sub(r"\*(.+?)\*", r"\1", content)
|
||||
# Remove bullet/number markers but keep text
|
||||
content = re.sub(r"^[-*+]\s+", "", content, flags=re.MULTILINE)
|
||||
content = re.sub(r"^\d+\.\s+", "", content, flags=re.MULTILINE)
|
||||
return content
|
||||
|
||||
|
||||
def strip_closing(content: str) -> str:
|
||||
"""Strip closing filler from the end of content."""
|
||||
for pattern in _CLOSING_PATTERNS:
|
||||
content = pattern.sub("", content)
|
||||
return content
|
||||
|
||||
|
||||
def clean_whitespace(content: str) -> str:
|
||||
"""Normalize whitespace — collapse multiple blank lines, trim edges."""
|
||||
# Collapse multiple blank lines to single
|
||||
content = re.sub(r"\n{3,}", "\n\n", content)
|
||||
# Strip leading/trailing whitespace
|
||||
content = content.strip()
|
||||
return content
|
||||
@@ -0,0 +1,164 @@
|
||||
"""
|
||||
Zerikah — extract vital content.
|
||||
|
||||
Architecture §3.5:
|
||||
Extract vital content — the Torah insight, the Hebrew analysis.
|
||||
|
||||
Like zerikah (sprinkling of blood on the altar), this step
|
||||
separates the vital from the incidental. What is kept:
|
||||
- Torah references (book/chapter/verse citations)
|
||||
- Hebrew text and root analysis
|
||||
- Novel insights grounded in text
|
||||
- Analytical claims with textual support
|
||||
|
||||
What is discarded (the hide, the offal):
|
||||
- Generic statements without textual grounding
|
||||
- Repetitive reformulations of the query
|
||||
- Social pleasantries and qualifiers
|
||||
- Ungrounded speculation
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import Tuple, List
|
||||
from korban_processor.korban import Korban
|
||||
|
||||
|
||||
# --- Extraction patterns ---
|
||||
|
||||
# Torah references: "Genesis 1:1", "Bereishit 1:1", "בראשית א:א"
|
||||
_TORAH_REF_PATTERN = re.compile(
|
||||
r"(?:"
|
||||
r"(?:Genesis|Bereishit|Exodus|Shemot|Leviticus|Vayikra|Numbers|Bamidbar|Deuteronomy|Devarim)"
|
||||
r"\s+\d+:\d+"
|
||||
r"|"
|
||||
r"(?:Gen|Exod?|Lev|Num|Deut)\.?\s+\d+:\d+"
|
||||
r"|"
|
||||
r"(?:בראשית|שמות|ויקרא|במדבר|דברים)\s+[\u05D0-\u05EA]+:[\u05D0-\u05EA]+"
|
||||
r")",
|
||||
re.UNICODE,
|
||||
)
|
||||
|
||||
# Hebrew text — sequences of Hebrew characters (with nikkud/teamim)
|
||||
_HEBREW_PATTERN = re.compile(
|
||||
r"[\u05B0-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7"
|
||||
r"\u05D0-\u05EA\u05F0-\u05F4\u0591-\u05AF]{2,}",
|
||||
re.UNICODE,
|
||||
)
|
||||
|
||||
# Root notation: ש-ר-ש or ש.ר.ש or shoresh patterns
|
||||
_ROOT_PATTERN = re.compile(
|
||||
r"(?:"
|
||||
r"[\u05D0-\u05EA][-.][\u05D0-\u05EA][-.][\u05D0-\u05EA]"
|
||||
r"|"
|
||||
r"root\s+[\u05D0-\u05EA]{2,3}"
|
||||
r"|"
|
||||
r"(?:shoresh|root)\s+[a-z]{3,}"
|
||||
r")",
|
||||
re.UNICODE | re.IGNORECASE,
|
||||
)
|
||||
|
||||
# Sentences containing analytical claims (contains "means", "indicates", "suggests")
|
||||
_INSIGHT_MARKERS = re.compile(
|
||||
r"(?:means?|indicates?|suggests?|implies?|reveals?|signifies?|"
|
||||
r"connects?\s+to|derives?\s+from|related\s+to|"
|
||||
r"parallels?|echoes?|alludes?\s+to|"
|
||||
r"the\s+root|this\s+root|the\s+shoresh|"
|
||||
r"gematria|numerical\s+value|"
|
||||
r"binyan|conjugation|"
|
||||
r"Rashi|Ramban|Rambam|Ibn\s+Ezra|Sforno|Onkelos|Targum|Midrash|Talmud|Gemara|Mishnah)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def zerikah(terminated_content: str, korban: Korban) -> Tuple[str, List[str]]:
|
||||
"""
|
||||
Extract vital content — the Torah insight, the Hebrew analysis.
|
||||
|
||||
Returns (vital_content, discarded_parts).
|
||||
|
||||
Args:
|
||||
terminated_content: Content after shechitah (stripped of voice/formatting)
|
||||
korban: Original korban (for context — provenance, query)
|
||||
|
||||
Returns:
|
||||
Tuple of (vital content string, list of discarded strings)
|
||||
"""
|
||||
if not terminated_content.strip():
|
||||
return "", []
|
||||
|
||||
sentences = split_sentences(terminated_content)
|
||||
vital_sentences: List[str] = []
|
||||
discarded_sentences: List[str] = []
|
||||
|
||||
for sentence in sentences:
|
||||
if is_vital(sentence):
|
||||
vital_sentences.append(sentence)
|
||||
else:
|
||||
discarded_sentences.append(sentence)
|
||||
|
||||
# If nothing was deemed vital, keep everything —
|
||||
# better to pass through than to discard all content
|
||||
if not vital_sentences and sentences:
|
||||
vital_sentences = sentences
|
||||
discarded_sentences = []
|
||||
|
||||
vital = " ".join(vital_sentences)
|
||||
return vital, discarded_sentences
|
||||
|
||||
|
||||
def is_vital(sentence: str) -> bool:
|
||||
"""
|
||||
Determine if a sentence contains vital content.
|
||||
|
||||
Vital = contains Torah references, Hebrew text, root analysis,
|
||||
or analytical insight markers.
|
||||
"""
|
||||
if not sentence.strip():
|
||||
return False
|
||||
|
||||
# Contains Torah reference
|
||||
if _TORAH_REF_PATTERN.search(sentence):
|
||||
return True
|
||||
|
||||
# Contains Hebrew text
|
||||
if _HEBREW_PATTERN.search(sentence):
|
||||
return True
|
||||
|
||||
# Contains root notation
|
||||
if _ROOT_PATTERN.search(sentence):
|
||||
return True
|
||||
|
||||
# Contains insight markers
|
||||
if _INSIGHT_MARKERS.search(sentence):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def split_sentences(text: str) -> List[str]:
|
||||
"""
|
||||
Split text into sentences.
|
||||
|
||||
Handles period, question mark, exclamation, and Hebrew sof-pasuk.
|
||||
Preserves sentence integrity — does not split on abbreviations
|
||||
or decimal points.
|
||||
"""
|
||||
# Split on sentence-ending punctuation followed by space or end
|
||||
parts = re.split(r"(?<=[.!?׃])\s+", text)
|
||||
# Filter empty strings
|
||||
return [p.strip() for p in parts if p.strip()]
|
||||
|
||||
|
||||
def extract_torah_references(text: str) -> List[str]:
|
||||
"""Extract all Torah references from text."""
|
||||
return _TORAH_REF_PATTERN.findall(text)
|
||||
|
||||
|
||||
def extract_hebrew_words(text: str) -> List[str]:
|
||||
"""Extract all Hebrew words/phrases from text."""
|
||||
return _HEBREW_PATTERN.findall(text)
|
||||
|
||||
|
||||
def extract_roots(text: str) -> List[str]:
|
||||
"""Extract all root notations from text."""
|
||||
return _ROOT_PATTERN.findall(text)
|
||||
Reference in new issue
Block a user