Code review fixes + 13 middot added to spec
Zerikah fail-safe: empty offerings rejected, not processed (BUILD_KORBAN §5). Halt monitor hardened: trap_exit, priority max, EXIT handler (Architecture spec). 13 Rules of Rabbi Yishmael added to Architecture §3.4 as Prolog inference predicates — the engine reasons WITH Torah's hermeneutic methods, not just about their products. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
33f8b03583
commit
f8f70c77e5
6 files changed
+150
-20
No files matched your search
@@ -78,6 +78,18 @@ def process_korban(
|
|||||||
# 3. Zerikah — extract vital content
|
# 3. Zerikah — extract vital content
|
||||||
vital, discarded = zerikah(terminated, korban)
|
vital, discarded = zerikah(terminated, korban)
|
||||||
|
|
||||||
|
# If zerikah found no vital content, the offering has no vital organs.
|
||||||
|
# BUILD_KORBAN.md §5: rejected, not processed into empty propositions.
|
||||||
|
if not vital.strip():
|
||||||
|
return ProcessedKorban(
|
||||||
|
vital_content="",
|
||||||
|
propositions=[],
|
||||||
|
provenance=source,
|
||||||
|
offering_type=offering_type,
|
||||||
|
discarded=discarded,
|
||||||
|
source_query=query,
|
||||||
|
)
|
||||||
|
|
||||||
# 4. Haktarah — transform to propositions
|
# 4. Haktarah — transform to propositions
|
||||||
propositions = haktarah(vital)
|
propositions = haktarah(vital)
|
||||||
|
|
||||||
|
|||||||
@@ -96,11 +96,12 @@ def zerikah(terminated_content: str, korban: Korban) -> Tuple[str, List[str]]:
|
|||||||
else:
|
else:
|
||||||
discarded_sentences.append(sentence)
|
discarded_sentences.append(sentence)
|
||||||
|
|
||||||
# If nothing was deemed vital, keep everything —
|
# If nothing was deemed vital, the offering has no vital organs.
|
||||||
# better to pass through than to discard all content
|
# BUILD_KORBAN.md §5: "the offering without vital organs is rejected,
|
||||||
|
# not processed into empty propositions."
|
||||||
|
# Return empty vital content — the caller handles rejection.
|
||||||
if not vital_sentences and sentences:
|
if not vital_sentences and sentences:
|
||||||
vital_sentences = sentences
|
discarded_sentences = sentences
|
||||||
discarded_sentences = []
|
|
||||||
|
|
||||||
vital = " ".join(vital_sentences)
|
vital = " ".join(vital_sentences)
|
||||||
return vital, discarded_sentences
|
return vital, discarded_sentences
|
||||||
|
|||||||
@@ -266,21 +266,17 @@ class TestBuildVerification5_EmptyOffering:
|
|||||||
"""System does not raise on empty offering — handles gracefully."""
|
"""System does not raise on empty offering — handles gracefully."""
|
||||||
assert isinstance(self.result, ProcessedKorban)
|
assert isinstance(self.result, ProcessedKorban)
|
||||||
|
|
||||||
def test_propositions_are_not_garbage(self):
|
def test_empty_offering_rejected_not_processed(self):
|
||||||
"""
|
"""
|
||||||
If propositions exist for an empty offering, they must still be valid Prolog terms.
|
The offering without vital organs is REJECTED — not processed
|
||||||
Empty or minimal propositions are acceptable — garbage propositions are not.
|
into empty propositions. BUILD_KORBAN.md §5.
|
||||||
"""
|
"""
|
||||||
for prop in self.result.propositions:
|
assert self.result.vital_content == ""
|
||||||
assert is_valid_prolog_term(prop), \
|
assert self.result.propositions == []
|
||||||
f"Garbage proposition from empty offering: {prop!r}"
|
|
||||||
|
|
||||||
def test_vital_content_has_no_assistant_voice(self):
|
def test_discarded_content_recorded(self):
|
||||||
"""Whatever survives, it must not contain assistant preamble."""
|
"""What was stripped is recorded — the hide and offal are diagnostic data."""
|
||||||
assert "Great question" not in self.result.vital_content
|
assert len(self.result.discarded) > 0
|
||||||
assert "I'd be happy" not in self.result.vital_content
|
|
||||||
assert "As an AI" not in self.result.vital_content
|
|
||||||
assert "Let me know" not in self.result.vital_content
|
|
||||||
|
|
||||||
def test_source_query_preserved(self):
|
def test_source_query_preserved(self):
|
||||||
assert self.result.source_query == "test empty"
|
assert self.result.source_query == "test empty"
|
||||||
|
|||||||
@@ -164,13 +164,16 @@ class TestZerikah:
|
|||||||
assert vital == ""
|
assert vital == ""
|
||||||
assert discarded == []
|
assert discarded == []
|
||||||
|
|
||||||
def test_all_filler_fallback_preserves_content(self):
|
def test_all_filler_rejected(self):
|
||||||
"""If nothing is vital, zerikah preserves everything rather than discarding all."""
|
"""
|
||||||
|
If nothing is vital, zerikah returns empty vital content.
|
||||||
|
BUILD_KORBAN.md §5: the offering without vital organs is rejected.
|
||||||
|
"""
|
||||||
filler = "There are many perspectives. People disagree. Context matters."
|
filler = "There are many perspectives. People disagree. Context matters."
|
||||||
korban = make_korban(filler)
|
korban = make_korban(filler)
|
||||||
vital, discarded = zerikah(filler, korban)
|
vital, discarded = zerikah(filler, korban)
|
||||||
# Since nothing qualifies as vital, fallback returns everything
|
assert vital == ""
|
||||||
assert vital != "" or discarded == []
|
assert len(discarded) > 0
|
||||||
|
|
||||||
def test_stateless_between_calls(self):
|
def test_stateless_between_calls(self):
|
||||||
"""Kiyyor principle: second call unaffected by first."""
|
"""Kiyyor principle: second call unaffected by first."""
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ check_vote(Vote) ->
|
|||||||
%%====================================================================
|
%%====================================================================
|
||||||
|
|
||||||
init([]) ->
|
init([]) ->
|
||||||
|
%% Architecture spec: halt monitor cannot be killed, cannot be bypassed,
|
||||||
|
%% highest priority. The halt monitor is the kohen gadol of process safety.
|
||||||
|
process_flag(trap_exit, true),
|
||||||
|
process_flag(priority, max),
|
||||||
{ok, #state{}}.
|
{ok, #state{}}.
|
||||||
|
|
||||||
handle_call({check_case, Case}, _From, State) ->
|
handle_call({check_case, Case}, _From, State) ->
|
||||||
@@ -71,6 +75,11 @@ handle_call(_Request, _From, State) ->
|
|||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
|
handle_info({'EXIT', _Pid, _Reason}, State) ->
|
||||||
|
%% Trap exit signals — halt monitor survives linked process deaths.
|
||||||
|
%% Architecture spec: "Cannot be killed by other components."
|
||||||
|
{noreply, State};
|
||||||
|
|
||||||
handle_info(_Info, State) ->
|
handle_info(_Info, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
|
|||||||
@@ -667,6 +667,106 @@ resolve(Case, Resolution) :-
|
|||||||
%% If no resolution is possible
|
%% If no resolution is possible
|
||||||
resolve(_, teiku).
|
resolve(_, teiku).
|
||||||
|
|
||||||
|
%% === 13 RULES OF RABBI YISHMAEL (Hermeneutic Inference) ===
|
||||||
|
%%
|
||||||
|
%% The Torah's own interpretive methods. The engine must reason WITH
|
||||||
|
%% these rules, not merely reason about mitzvot derived from them.
|
||||||
|
%% Each middah is a Prolog inference predicate that derives new
|
||||||
|
%% propositions from existing Torah facts.
|
||||||
|
|
||||||
|
%% 1. Kal va'chomer — a fortiori (minor to major)
|
||||||
|
%% If a lenient case has restriction X, a stricter case certainly does.
|
||||||
|
kal_vachomer(Lenient, Strict, Property) :-
|
||||||
|
has_property(Lenient, Property),
|
||||||
|
stricter_than(Strict, Lenient).
|
||||||
|
|
||||||
|
%% 2. Gezerah shavah — verbal analogy
|
||||||
|
%% Shared language between two passages implies shared law.
|
||||||
|
gezerah_shavah(VerseA, VerseB, SharedLaw) :-
|
||||||
|
verse_contains_word(VerseA, Word),
|
||||||
|
verse_contains_word(VerseB, Word),
|
||||||
|
has_law(VerseA, SharedLaw).
|
||||||
|
|
||||||
|
%% 3. Binyan av mi'katuv echad — prototype from one verse
|
||||||
|
%% A law stated in one case applies to all similar cases.
|
||||||
|
binyan_av(SourceVerse, TargetCase, Law) :-
|
||||||
|
has_law(SourceVerse, Law),
|
||||||
|
similar_case(SourceVerse, TargetCase),
|
||||||
|
\+ explicitly_excluded(TargetCase, Law).
|
||||||
|
|
||||||
|
%% 4. Binyan av mi'shnei ketuvim — prototype from two verses
|
||||||
|
%% A law common to two cases applies to all similar cases.
|
||||||
|
binyan_av_two(VerseA, VerseB, TargetCase, Law) :-
|
||||||
|
has_law(VerseA, Law),
|
||||||
|
has_law(VerseB, Law),
|
||||||
|
similar_case(VerseA, TargetCase),
|
||||||
|
\+ explicitly_excluded(TargetCase, Law).
|
||||||
|
|
||||||
|
%% 5. Klal u'frat — general and particular
|
||||||
|
%% A general statement followed by a particular limits to the particular.
|
||||||
|
klal_ufrat(General, Particular, Scope) :-
|
||||||
|
follows(General, Particular),
|
||||||
|
Scope = limited_to(Particular).
|
||||||
|
|
||||||
|
%% 6. Frat u'klal — particular and general
|
||||||
|
%% A particular followed by a general expands to the general.
|
||||||
|
frat_uklal(Particular, General, Scope) :-
|
||||||
|
follows(Particular, General),
|
||||||
|
Scope = expanded_to(General).
|
||||||
|
|
||||||
|
%% 7. Klal u'frat u'klal — general, particular, general
|
||||||
|
%% Scope is determined by similarity to the particular.
|
||||||
|
klal_frat_klal(General1, Particular, General2, Scope) :-
|
||||||
|
follows(General1, Particular),
|
||||||
|
follows(Particular, General2),
|
||||||
|
Scope = similar_to(Particular).
|
||||||
|
|
||||||
|
%% 8. Klal she'hu tzarikh li'frat, u'frat she'hu tzarikh li'klal
|
||||||
|
%% General needing particular, particular needing general — mutual dependency.
|
||||||
|
klal_tzarikh_frat(General, Particular, Meaning) :-
|
||||||
|
requires_specification(General, Particular),
|
||||||
|
requires_generalization(Particular, General),
|
||||||
|
Meaning = mutual_definition(General, Particular).
|
||||||
|
|
||||||
|
%% 9. Davar she'hayah bi'khlal v'yatza min ha'klal l'lamed
|
||||||
|
%% Something included in a general rule that is singled out teaches
|
||||||
|
%% about the general rule, not only about itself.
|
||||||
|
davar_yatza_l_lamed(General, Exception, Teaching) :-
|
||||||
|
member_of(Exception, General),
|
||||||
|
singled_out(Exception, General),
|
||||||
|
Teaching = teaches_about(General, Exception).
|
||||||
|
|
||||||
|
%% 10. Davar she'hayah bi'khlal v'yatza lit'on to'an acher
|
||||||
|
%% Something singled out to teach a new matter — applies only to itself.
|
||||||
|
davar_yatza_toan_acher(General, Exception, NewMatter) :-
|
||||||
|
member_of(Exception, General),
|
||||||
|
singled_out_for(Exception, NewMatter),
|
||||||
|
applies_only_to(NewMatter, Exception).
|
||||||
|
|
||||||
|
%% 11. Davar she'hayah bi'khlal v'yatza la'don ba'davar he'chadash
|
||||||
|
%% Something singled out for a completely new category — cannot return
|
||||||
|
%% to the general rule unless Scripture explicitly returns it.
|
||||||
|
davar_yatza_chadash(General, Exception, NewCategory) :-
|
||||||
|
member_of(Exception, General),
|
||||||
|
new_category(Exception, NewCategory),
|
||||||
|
\+ explicitly_returned(Exception, General).
|
||||||
|
|
||||||
|
%% 12. Davar ha'lamed me'inyano, v'davar ha'lamed mi'sofo
|
||||||
|
%% Meaning derived from context, meaning derived from conclusion.
|
||||||
|
davar_lamed_inyan(Passage, ContextMeaning) :-
|
||||||
|
surrounding_context(Passage, Context),
|
||||||
|
implies(Context, ContextMeaning).
|
||||||
|
davar_lamed_sofo(Passage, ConclusionMeaning) :-
|
||||||
|
conclusion_of(Passage, Conclusion),
|
||||||
|
implies(Conclusion, ConclusionMeaning).
|
||||||
|
|
||||||
|
%% 13. Shnei ketuvim ha'makhchishim zeh et zeh
|
||||||
|
%% Two verses that contradict — resolved by a third verse.
|
||||||
|
shnei_ketuvim(VerseA, VerseB, VerseC, Resolution) :-
|
||||||
|
contradicts(VerseA, VerseB),
|
||||||
|
resolves_contradiction(VerseC, VerseA, VerseB),
|
||||||
|
Resolution = harmonized(VerseA, VerseB, VerseC).
|
||||||
|
|
||||||
%% === HALT CONDITIONS ===
|
%% === HALT CONDITIONS ===
|
||||||
|
|
||||||
%% Check for avodah zarah — misattributed authority
|
%% Check for avodah zarah — misattributed authority
|
||||||
@@ -700,6 +800,15 @@ talmudic_engine/
|
|||||||
│ │ ├── challenge.pl -- Kushya generation
|
│ │ ├── challenge.pl -- Kushya generation
|
||||||
│ │ ├── resolve.pl -- Dialectical resolution
|
│ │ ├── resolve.pl -- Dialectical resolution
|
||||||
│ │ └── teiku.pl -- Unresolved tension handling
|
│ │ └── teiku.pl -- Unresolved tension handling
|
||||||
|
│ ├── middot/
|
||||||
|
│ │ ├── middot.pl -- 13 Rules of Rabbi Yishmael as inference predicates
|
||||||
|
│ │ ├── kal_vachomer.pl -- Rule 1: a fortiori (minor to major)
|
||||||
|
│ │ ├── gezerah_shavah.pl -- Rule 2: verbal analogy
|
||||||
|
│ │ ├── binyan_av.pl -- Rules 3-4: prototype from one/two verses
|
||||||
|
│ │ ├── klal_ufrat.pl -- Rules 5-8: general/particular interactions
|
||||||
|
│ │ ├── davar_yatza.pl -- Rules 9-11: exception teaching rules
|
||||||
|
│ │ ├── lamed_inyan.pl -- Rule 12: meaning from context/conclusion
|
||||||
|
│ │ └── shnei_ketuvim.pl -- Rule 13: contradicting verses resolved by third
|
||||||
│ ├── halt/
|
│ ├── halt/
|
||||||
│ │ ├── avodah_zarah.pl -- Idolatry detection
|
│ │ ├── avodah_zarah.pl -- Idolatry detection
|
||||||
│ │ ├── shfichut_damim.pl -- Destruction detection
|
│ │ ├── shfichut_damim.pl -- Destruction detection
|
||||||
|
|||||||
Reference in new issue
Block a user