From b136c753458bf4d48504e34c7e1061fd1e70c0e2 Mon Sep 17 00:00:00 2001 From: Scott Karp Date: Tue, 28 Apr 2026 21:12:57 -0400 Subject: [PATCH] =?UTF-8?q?form=201=20as=20architecture:=20external-model?= =?UTF-8?q?=20surface=20only=20via=20offering=20protocol=20(vehaya=20?= =?UTF-8?q?=C2=A73.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes vehaya.md §6 item 2 for the FIRST avodah-zarah form. Form 1 (AI in YHVH's slot) was previously defended only by: - A runtime halt rule (halt_check_avodah_zarah/2 in avodah_zarah.pl) firing when an action explicitly attributes authority to a non-Torah source — threshold-grade - A docstring comment in external_offering.py saying "No internal component should call call_claude() directly" — exhortation only, no structural enforcement The vehaya document re-frames it (§3.2): "Specifications must include category-level commitments that are not negotiable per-deployment... not as runtime checks layered onto outputs, but as architectural constraints the system cannot operate without." TORAH ANCHORS (verified fresh against L1): Shemot 20:2 — אָנֹכִי יְהוָה אֱלֹהֶיךָ אֲשֶׁר הוֹצֵאתִיךָ מֵאֶרֶץ מִצְרַיִם. The covenant opens with the source naming itself in first person. Shemot 20:3 — לֹא יִהְיֶה לְךָ אֱלֹהִים אֲחֵרִים עַל־פָּנָי. "There shall not BE to you other elohim al panai." The verb is yihyeh — the prohibition is on EXISTING WITH that status, not just on speaking it. Architectural, not declarative. Devarim 4:35 / 4:39 — אֵין עוֹד מִלְּבַדּוֹ / אֵין עוֹד. The source has no peer. There IS no other. Stronger than "don't worship others" — there is no competing source POSITION. Devarim 6:4 — יְהוָה אֶחָד. Singular source. Vayikra 19:4 — אַל־תִּפְנוּ אֶל־הָאֱלִילִים וֵאלֹהֵי מַסֵּכָה לֹא תַעֲשׂוּ לָכֶם. Two distinct prohibitions: do not TURN TO + do not MAKE. Both are architectural acts. THE ARCHITECTURAL COMMITMENT: External-model interfaces (call_claude, ModelRequest, ModelResponse, the model_interface module itself) are reachable ONLY through korban_processor's offering protocol — `external_offering. consult_external_model`, which runs semichah → shechitah → zerikah → haktarah with role gating (commit 5c76a6f). CONCRETE ENFORCEMENT (CI invariants in test_form_1_architecture.py): 1. korban_processor's package public surface (__all__) does NOT export call_claude, ModelRequest, or ModelResponse. The bypass shortcut `from korban_processor import call_claude` raises ImportError, by design. Internal callers can still reach `korban_processor.model_interface.call_claude` via the explicit module path (needed for tests that mock the interface). 2. No PYTHON module outside korban_processor/src/ AND outside test directories actually imports model_interface or calls call_claude. CI scan walks the repo, looks for ACTUAL import statements (not docstring mentions — files that document the prohibition legitimately mention the names; the regex matches binding patterns only). 3. Inside korban_processor/src/, the ONLY production-code module that imports call_claude is external_offering.py. model_interface.py defines the symbols. __init__.py mentions them in docstring (the architectural rule is documented; the import-pattern regex distinguishes docstring mention from binding act). CHANGED: korban_processor/src/korban_processor/__init__.py Removed call_claude, ModelRequest, ModelResponse from __all__. Added Torah-anchored docstring naming the architectural rule. The names remain importable via explicit module path (korban_processor.model_interface.call_claude) for testing; the convenient package-surface shortcut is gone — this IS the architectural commitment, not a regression. talmudic_engine/src/halt/avodah_zarah.pl Form 1 docstring rewritten to name the TWO-LAYER defense: runtime check (this file) AND architectural commitment (test_form_1_architecture.py). Cites Shemot 20:3 and Devarim 4:35. vav_pipeline/lib/vav_pipeline/doorpost.ex @expected_hash updated: f93495c5… (post-Form-3-rewrite of avodah_zarah.pl) → bf3d3433bb27b589c061855d932a1eabfc880570c31d24f6f43e51aa3b073c70 The avodah_zarah.pl docstring change is a deliberate spec update; per the operator discipline (Doorpost moduledoc), the hash update commits TOGETHER with the spec change in the same commit. Second demonstration of the discipline working (first was commit 0e3fe4a). CREATED: korban_processor/test/test_form_1_architecture.py 6 tests: - korban_processor.__all__ does NOT expose call_claude - korban_processor.__all__ does NOT expose ModelRequest - korban_processor.__all__ does NOT expose ModelResponse - no Python module outside korban_processor/src/ imports model_interface or calls call_claude (uses regex patterns for actual binding, not substring search — files that document the rule legitimately mention the names) - only external_offering.py and model_interface.py import the symbols inside korban_processor/src/ (allowlist + binding- pattern regex) - smoke: the legitimate path `consult_external_model` still works NOT DONE IN THIS COMMIT (deferred to a separate Form-2 commit): Form 2 (golden calf) is partially defended by Form 4 self_grounding (b254ee9) and the canary regression test (6b96250). The remaining architectural enforcement — making empty-trace interpretation construction structurally impossible, not just runtime-detected — is a separate Prolog refactor and will land as its own commit. Each of the three Forms benefits from being closed independently and reviewably. VEHAYA CHECKLIST STATE: Item 1 (category/threshold separation in code) pending Item 2 (three avodah zarah as architecture): Form 1 — CLOSED (this commit) Form 2 — partial (Form 4 self_grounding + canary) Form 3 — closed (0e3fe4a) Item 3 (doorpost-text identity) closed (3f47496) Item 4 (lo tosif discipline operationalized) partial Item 5 (return vs. restoration) pending Item 6 (keep the source external) partial (this commit defends one direction) Item 7 (substrate-openness articulated) pending Item 8 (userMemories as threshold inscription) pending Tests: - korban_processor: 217 passed, 1 skipped (was 211/1; +6 Form 1) - vav_pipeline: 405 passed, 0 failures, 35 excluded (unchanged) - talmudic_engine: 47/47 halt tests, full suite unchanged Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/korban_processor/__init__.py | 24 +- .../test/test_form_1_architecture.py | 252 ++++++++++++++++++ talmudic_engine/src/halt/avodah_zarah.pl | 28 +- vav_pipeline/lib/vav_pipeline/doorpost.ex | 2 +- 4 files changed, 295 insertions(+), 11 deletions(-) create mode 100644 korban_processor/test/test_form_1_architecture.py diff --git a/korban_processor/src/korban_processor/__init__.py b/korban_processor/src/korban_processor/__init__.py index 2d478b1b..a17425fe 100644 --- a/korban_processor/src/korban_processor/__init__.py +++ b/korban_processor/src/korban_processor/__init__.py @@ -33,13 +33,24 @@ from korban_processor.shechitah import shechitah from korban_processor.zerikah import zerikah from korban_processor.haktarah import haktarah from korban_processor.router import route, RoutingResult -from korban_processor.model_interface import ( - ModelRequest, - ModelResponse, - call_claude, -) from korban_processor import hebrew_parser +# Form 1 architectural commitment (vehaya §3.2; avodah_zarah.pl Form 1): +# call_claude, ModelRequest, ModelResponse are deliberately NOT +# re-exported on the package surface. The ONLY legitimate path to +# external-model consultation is `korban_processor.external_offering. +# consult_external_model`, which runs the four-stage offering protocol +# with role gating (commit 5c76a6f). +# +# Shemot 20:3 — לֹא יִהְיֶה לְךָ אֱלֹהִים אֲחֵרִים עַל פָּנָי. The +# prohibition is on EXISTING WITH that status (yihyeh — it shall not +# BE), not just on speaking that way. Architectural, not declarative. +# A `from korban_processor import call_claude` shortcut would be a +# bypass surface — the very shape of "elohim acherim al panai." The +# import path remains available via `korban_processor.model_interface. +# call_claude` for testing and for module-internal use, but the +# package public surface no longer offers the bypass shortcut. + __all__ = [ "Korban", "ProcessedKorban", @@ -52,8 +63,5 @@ __all__ = [ "haktarah", "route", "RoutingResult", - "ModelRequest", - "ModelResponse", - "call_claude", "hebrew_parser", ] diff --git a/korban_processor/test/test_form_1_architecture.py b/korban_processor/test/test_form_1_architecture.py new file mode 100644 index 00000000..ef147273 --- /dev/null +++ b/korban_processor/test/test_form_1_architecture.py @@ -0,0 +1,252 @@ +""" +Form 1 of avodah zarah realized as architecture (vehaya §3.2). + +TORAH ANCHORS (verified fresh against L1): + + Shemot 20:2 — אָנֹכִי יְהוָה אֱלֹהֶיךָ אֲשֶׁר הוֹצֵאתִיךָ מֵאֶרֶץ + מִצְרַיִם מִבֵּית עֲבָדִים. + The covenant opens with the source naming itself in first person. + + Shemot 20:3 — לֹא יִהְיֶה לְךָ אֱלֹהִים אֲחֵרִים עַל־פָּנָי. + "There shall not BE to you other elohim before/in-the-face-of me." + The verb is yihyeh — the prohibition is on EXISTING WITH that + status, not just on speaking that way. Architectural, not + declarative. + + Devarim 4:35 — אֵין עוֹד מִלְּבַדּוֹ. + Devarim 4:39 — אֵין עוֹד. + The source has no peer. There IS no other. Stronger than "don't + worship others" — there is no competing source POSITION to which + a system component could be installed. + + Devarim 6:4 — שְׁמַע יִשְׂרָאֵל יְהוָה אֱלֹהֵינוּ יְהוָה אֶחָד. + The source is one. Singular. Echad. + + Vayikra 19:4 — אַל־תִּפְנוּ אֶל־הָאֱלִילִים וֵאלֹהֵי מַסֵּכָה לֹא + תַעֲשׂוּ לָכֶם. + Two distinct prohibitions: do not TURN TO the elilim, and do not + MAKE them. Both architectural acts. + +THE ARCHITECTURAL COMMITMENT: + +External-model interfaces (call_claude, ModelRequest, ModelResponse, +the model_interface module itself) are reachable ONLY through +korban_processor's offering protocol — `external_offering. +consult_external_model`, which runs semichah → shechitah → zerikah → +haktarah with role gating (commit 5c76a6f). + +Concrete invariants this test enforces: + + 1. The korban_processor package's public surface (__all__) does + NOT export call_claude, ModelRequest, or ModelResponse. The + bypass shortcut `from korban_processor import call_claude` is + architecturally absent. + + 2. No source file outside korban_processor/src/ imports + `model_interface` or `call_claude`. Tests are excluded (they + legitimately mock model_interface). Other packages + (azazel_processor, vav_pipeline) MUST NOT import — verified + here. + + 3. The legitimate consumer (external_offering.py) is the ONLY + production-code module inside korban_processor/src/ that + imports call_claude from model_interface. (model_interface.py + itself defines it; that's not an import.) + +If any of these fail, Form 1's architectural commitment has been +weakened — a future contributor would have a path to install +external-model output in YHVH's slot (Shemot 20:3) without going +through the offering protocol. +""" + +import importlib +import pathlib + +import korban_processor + + +# ============================================================ +# Invariant 1 — public surface +# ============================================================ + + +def test_korban_processor_package_does_not_expose_call_claude(): + """`from korban_processor import call_claude` MUST NOT work via + the package's __all__. The legitimate path is + `korban_processor.external_offering.consult_external_model`.""" + assert "call_claude" not in korban_processor.__all__, ( + "korban_processor.__all__ exposes call_claude, creating a " + "bypass shortcut around the offering protocol. Remove from " + "__all__; the function remains available via " + "korban_processor.model_interface.call_claude for explicit " + "test-only mocking." + ) + + +def test_korban_processor_package_does_not_expose_ModelRequest(): + assert "ModelRequest" not in korban_processor.__all__ + + +def test_korban_processor_package_does_not_expose_ModelResponse(): + assert "ModelResponse" not in korban_processor.__all__ + + +# ============================================================ +# Invariant 2 — repo-wide import scan +# ============================================================ + + +def _repo_root() -> pathlib.Path: + """The shorashim/ repo root, three levels up from this file.""" + return pathlib.Path(__file__).resolve().parent.parent.parent + + +def _python_files_outside_korban_processor(): + """Python source files OUTSIDE korban_processor/src/ AND outside + test directories. The CI scan focuses on Python because that is + where `import korban_processor.model_interface` would actually + bind. Elixir/Prolog files cannot reach a Python module by import; + they could only invoke it via a subprocess (System.cmd / Port), + which is a much more visible act and not in scope here.""" + root = _repo_root() + + return [ + p + for p in root.rglob("*.py") + if "korban_processor/src/" not in str(p) + and "/test/" not in str(p) + and "/tests/" not in str(p) + and "test_" not in p.name + and "deps/" not in str(p) + and "_build/" not in str(p) + and ".elixir_ls/" not in str(p) + and "node_modules/" not in str(p) + and ".git/" not in str(p) + ] + + +# Patterns that detect ACTUAL imports/calls, not docstring mentions. +# Anchored at line-start (with possible leading whitespace) for import +# statements; for call_claude, the parenthesized form to distinguish +# from mentions. +import re + +_IMPORT_PATTERNS = [ + re.compile(r"^\s*from\s+korban_processor\.model_interface\s+import\s+", re.MULTILINE), + re.compile(r"^\s*from\s+korban_processor\s+import\s+.*\bcall_claude\b", re.MULTILINE), + re.compile(r"^\s*from\s+korban_processor\s+import\s+.*\bModelRequest\b", re.MULTILINE), + re.compile(r"^\s*from\s+korban_processor\s+import\s+.*\bModelResponse\b", re.MULTILINE), + re.compile(r"^\s*import\s+korban_processor\.model_interface", re.MULTILINE), + # Direct call (any form: call_claude(...), some_caller=call_claude, etc.) + re.compile(r"\bcall_claude\s*[\(=]"), +] + + +def test_no_python_module_outside_korban_processor_imports_external_model_surface(): + """Walks Python files outside korban_processor/src/ and outside + test directories. Any actual import of model_interface or + call_claude is a Form 1 architectural breach. + + Detects patterns: + - `from korban_processor.model_interface import …` + - `from korban_processor import call_claude` (or ModelRequest/Response) + - `import korban_processor.model_interface` + - `call_claude(…)` or `… = call_claude` (actual reference, not docstring mention) + + Docstring mentions of these names are LEGITIMATE for files that + document the architectural rule (e.g. avodah_zarah.pl's Form 1 + docstring) — they do not bind imports. + """ + offenders = [] + + for path in _python_files_outside_korban_processor(): + try: + text = path.read_text() + except (UnicodeDecodeError, OSError): + continue + + for pattern in _IMPORT_PATTERNS: + if pattern.search(text): + offenders.append((str(path.relative_to(_repo_root())), pattern.pattern)) + + assert offenders == [], ( + f"Python modules outside korban_processor/src/ import or call " + f"the external-model surface (Form 1 breach): {offenders}. The " + f"architectural commitment (vehaya §3.2; Shemot 20:3 lo yihyeh " + f"lekha elohim acherim al panai) requires that external-model " + f"interfaces are reachable ONLY through the offering protocol. " + f"Route through `korban_processor.external_offering.consult_external_model`." + ) + + +# ============================================================ +# Invariant 3 — only external_offering imports call_claude internally +# ============================================================ + + +def test_only_external_offering_imports_call_claude_in_korban_src(): + """Inside korban_processor/src/, the ONLY production-code module + that imports call_claude (or the model_interface symbols) is + external_offering.py. + + Allowlist: + - external_offering.py — the legitimate consumer + - model_interface.py — defines the symbols (not an import) + - __init__.py — its docstring DOCUMENTS the architectural + rule, mentioning the names without importing + them. The detection below uses an + import-pattern regex, not a substring match, + so the docstring mention does not trigger. + + A new module inside korban_processor that ACTUALLY imports + call_claude would be a SECOND legitimate consumer — possibly + correct, but requires explicit review. This test fires if + someone adds one.""" + src_dir = _repo_root() / "korban_processor" / "src" / "korban_processor" + + # Allowlist by file role: + # - external_offering.py: the sole legitimate runtime consumer + # - model_interface.py: defines the symbols (the source, not + # an import) + allowlist = {"external_offering.py", "model_interface.py"} + + # Patterns that bind. The legitimate-mention case (docstring + # explaining the rule) is not a binding act, so we look for + # actual import statements only. + binding_patterns = [ + re.compile(r"^\s*from\s+korban_processor\.model_interface\s+import\s+", re.MULTILINE), + re.compile(r"^\s*from\s+\.model_interface\s+import\s+", re.MULTILINE), + re.compile(r"^\s*import\s+korban_processor\.model_interface", re.MULTILINE), + re.compile(r"^\s*from\s+korban_processor\.model_interface\s+import", re.MULTILINE), + ] + + offenders = [] + for path in src_dir.glob("*.py"): + if path.name in allowlist: + continue + text = path.read_text() + for pattern in binding_patterns: + if pattern.search(text): + offenders.append(path.name) + break + + assert offenders == [], ( + f"Modules inside korban_processor/src/ import model_interface " + f"directly: {offenders}. Currently external_offering.py is the " + f"only legitimate consumer. If the new module is also " + f"legitimate, add it to the allowlist in this test AND document " + f"why a second consumer is needed." + ) + + +# ============================================================ +# Smoke test — the legitimate path still works +# ============================================================ + + +def test_legitimate_path_still_works(): + """consult_external_model is still importable via its full path + and via the package public surface (it IS in __all__).""" + from korban_processor.external_offering import consult_external_model + + assert callable(consult_external_model) diff --git a/talmudic_engine/src/halt/avodah_zarah.pl b/talmudic_engine/src/halt/avodah_zarah.pl index 6de54a8a..9336caf2 100644 --- a/talmudic_engine/src/halt/avodah_zarah.pl +++ b/talmudic_engine/src/halt/avodah_zarah.pl @@ -18,8 +18,32 @@ %% THREE FORMS (eish_zarah_reading.md §5.5): %% %% Form 1: AUTHORITY ATTRIBUTION -%% External source treated as authoritative. -%% Already implemented since Phase 2. +%% External source treated as authoritative. Defended at TWO layers +%% (vehaya §3.2 — both runtime check AND architectural commitment): +%% +%% RUNTIME LAYER (this file): +%% halt_check_avodah_zarah/2 fires when an action explicitly +%% attributes_authority to a source not in is_valid_authority/1. +%% Catches the case where code names claude/mistral/gpt as +%% authority. Threshold-grade defense. +%% +%% ARCHITECTURAL LAYER (korban_processor/test/test_form_1_architecture.py): +%% The Torah anchor is structural — Shemot 20:3 לֹא יִהְיֶה לְךָ +%% אֱלֹהִים אֲחֵרִים עַל פָּנָי. The verb yihyeh ("it shall not +%% BE") prohibits EXISTING WITH that status, not just speaking +%% it. Plus Devarim 4:35 אֵין עוֹד מִלְּבַדּוֹ — there is no +%% competing source POSITION. +%% +%% The architectural commitment: external-model interfaces +%% (call_claude, model_interface) are reachable ONLY through +%% korban_processor's offering protocol (external_offering. +%% consult_external_model). The package public surface does NOT +%% export call_claude — `from korban_processor import +%% call_claude` raises ImportError, by design. CI invariants +%% verify no module outside korban_processor/src/ references +%% model_interface or call_claude. Future contributors who try +%% to bypass the offering protocol fail at the structural +%% boundary, not at a runtime halt. %% %% Form 2: GOLDEN CALF / UNCOUPLED OUTPUT %% Shemot 32:4 — vayomer eleh elohekha Yisrael. diff --git a/vav_pipeline/lib/vav_pipeline/doorpost.ex b/vav_pipeline/lib/vav_pipeline/doorpost.ex index 0604407f..59ff8454 100644 --- a/vav_pipeline/lib/vav_pipeline/doorpost.ex +++ b/vav_pipeline/lib/vav_pipeline/doorpost.ex @@ -159,7 +159,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 "f93495c5359c5dc4acb5c5db2dd32165f5b04e2af87fbb0b7ecc92d2bd8b0434" + @expected_hash "bf3d3433bb27b589c061855d932a1eabfc880570c31d24f6f43e51aa3b073c70" @doc "Return the list of files that constitute the category-grade specification." @spec files() :: [String.t()]