Phase 3: Intelligence — 613 mitzvot, 13 middot, Tzara'at diagnostic
Encode all 613 mitzvot from Rambam's Sefer HaMitzvot (248 positive, 365 prohibitions). Build the 13 Middot of Rabbi Yishmael as Prolog inference predicates for hermeneutical reasoning. Implement Tzara'at multi-stage input validation following Vayikra 13-14. Enhance kushya generation with kal vachomer and shnei ketuvim challenge strategies. Architecture §4 Steps 14-15, 19-20. New files: middot/ — 8 files (master + 7 rule modules) diagnostic/ — 4 files (tzaraat, inspection, quarantine, diagnosis) Modified: mitzvot.pl — 52 → 613 mitzvot relationships.pl — expanded tensions, complements, action domains challenge.pl — middot-based kushya (kal vachomer, shnei ketuvim) Tests: 293 total (184 Prolog, 76 Elixir, 33 Haskell), 0 failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
ae78ed26d1
commit
52837cee18
19 files changed
+2795
-178
No files matched your search
@@ -0,0 +1,353 @@
|
||||
%% middot_test.pl — Tests for the 13 Middot of Rabbi Yishmael.
|
||||
%%
|
||||
%% Phase 3: Hermeneutical inference predicates.
|
||||
|
||||
:- use_module(library(plunit)).
|
||||
:- use_module('../src/middot/middot').
|
||||
:- use_module('../src/middot/kal_vachomer').
|
||||
:- use_module('../src/middot/gezerah_shavah').
|
||||
:- use_module('../src/middot/binyan_av').
|
||||
:- use_module('../src/middot/klal_ufrat').
|
||||
:- use_module('../src/middot/davar_yatza').
|
||||
:- use_module('../src/middot/lamed_inyan').
|
||||
:- use_module('../src/middot/shnei_ketuvim').
|
||||
:- use_module('../src/specification/mitzvot').
|
||||
:- use_module('../src/specification/torah_text').
|
||||
:- use_module('../src/specification/root_meanings').
|
||||
|
||||
%% ============================================================
|
||||
%% MASTER MODULE TESTS
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(middot_master).
|
||||
|
||||
%% All 13 middot are named
|
||||
test(all_thirteen_named) :-
|
||||
findall(N, middah_name(N, _), Numbers),
|
||||
length(Numbers, 13).
|
||||
|
||||
%% all_middot returns a list of 13 names
|
||||
test(all_middot_list) :-
|
||||
all_middot(Middot),
|
||||
length(Middot, 13).
|
||||
|
||||
%% Key middot names are correct
|
||||
test(middah_1_is_kal_vachomer) :-
|
||||
middah_name(1, kal_vachomer).
|
||||
|
||||
test(middah_2_is_gezerah_shavah) :-
|
||||
middah_name(2, gezerah_shavah).
|
||||
|
||||
test(middah_13_is_shnei_ketuvim) :-
|
||||
middah_name(13, shnei_ketuvim).
|
||||
|
||||
%% apply_middah works for rule 1 (kal vachomer)
|
||||
test(apply_middah_1, [nondet]) :-
|
||||
apply_middah(1, shabbat_rest, festival_rest, _Reasoning).
|
||||
|
||||
%% apply_middah works for rule 5 (klal ufrat)
|
||||
test(apply_middah_5, [nondet]) :-
|
||||
apply_middah(5,
|
||||
general(fruit_trees),
|
||||
particular([olive, grape]),
|
||||
narrowed_to([olive, grape], from(fruit_trees))).
|
||||
|
||||
:- end_tests(middot_master).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULE 1: KAL VACHOMER
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(kal_vachomer_tests).
|
||||
|
||||
%% Severity ordering: monetary < physical < capital < divine
|
||||
test(monetary_less_than_physical) :-
|
||||
severity_ordering(monetary, physical).
|
||||
|
||||
test(physical_less_than_capital) :-
|
||||
severity_ordering(physical, capital).
|
||||
|
||||
test(capital_less_than_divine) :-
|
||||
severity_ordering(capital, divine).
|
||||
|
||||
%% Transitive stringency
|
||||
test(monetary_less_than_capital) :-
|
||||
is_more_stringent(monetary, capital).
|
||||
|
||||
test(monetary_less_than_divine) :-
|
||||
is_more_stringent(monetary, divine).
|
||||
|
||||
%% Kal vachomer: shabbat → festival
|
||||
test(shabbat_to_festival) :-
|
||||
kal_vachomer(shabbat_rest, festival_rest, _, definite).
|
||||
|
||||
%% Kal vachomer: monetary → physical compensation
|
||||
test(monetary_to_physical) :-
|
||||
kal_vachomer(compensate_monetary, compensate_physical, _, definite).
|
||||
|
||||
%% Kal vachomer: domain-based derivation
|
||||
test(domain_derivation, [nondet]) :-
|
||||
kal_vachomer(
|
||||
law_in(monetary, _),
|
||||
law_in(physical, _),
|
||||
derived(_, from(monetary), to(physical), kal_vachomer),
|
||||
definite
|
||||
).
|
||||
|
||||
%% Unconditional mitzvah implies conditional
|
||||
test(unconditional_implies_conditional, [nondet]) :-
|
||||
kal_vachomer(
|
||||
mitzvah_applies(1, always),
|
||||
mitzvah_applies(1, when(_)),
|
||||
derived(1, unconditional_implies_conditional, kal_vachomer),
|
||||
definite
|
||||
).
|
||||
|
||||
%% Dayo principle: derived law equals source law
|
||||
test(dayo_principle) :-
|
||||
kal_vachomer:dayo(derived(some_law, _, _, _), some_law).
|
||||
|
||||
:- end_tests(kal_vachomer_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULE 2: GEZERAH SHAVAH
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(gezerah_shavah_tests).
|
||||
|
||||
%% Known gezerah shavah: shabbat ↔ pesach (shemirah)
|
||||
test(shabbat_pesach_shemirah) :-
|
||||
gezerah_shavah(shabbat_keeping, pesach_keeping, _, shin_mem_resh).
|
||||
|
||||
%% Known gezerah shavah: shabbat ↔ circumcision (ot)
|
||||
test(shabbat_circumcision_ot) :-
|
||||
gezerah_shavah(shabbat_sign, circumcision_sign, _, aleph_vav_tav).
|
||||
|
||||
%% Shared keyword: two verses sharing a root link
|
||||
test(shared_keyword_creation, [nondet]) :-
|
||||
shared_keyword(ref(bereishit, 1, 1), ref(bereishit, 1, 27), bet_resh_aleph).
|
||||
|
||||
%% Dynamic gezerah shavah from Torah text
|
||||
test(dynamic_gezerah_shavah, [nondet]) :-
|
||||
gezerah_shavah(ref(bereishit, 1, 1), ref(bereishit, 1, 27), _, bet_resh_aleph).
|
||||
|
||||
:- end_tests(gezerah_shavah_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULES 3-4: BINYAN AV
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(binyan_av_tests).
|
||||
|
||||
%% Binyan av from one verse: source verse establishes domain law
|
||||
%% Using Shemot 20:8 — mitzvah 154 (rest_on_shabbat), root qof_dalet_shin → holiness
|
||||
test(binyan_av_one_verse, [nondet]) :-
|
||||
binyan_av_one(ref(shemot, 20, 8), applies_to_domain(_, _), _).
|
||||
|
||||
%% Binyan av from two verses: common root found
|
||||
test(binyan_av_two_verses, [nondet]) :-
|
||||
binyan_av_two(
|
||||
ref(bereishit, 1, 1),
|
||||
ref(bereishit, 1, 27),
|
||||
general_rule(bet_resh_aleph, creation),
|
||||
bet_resh_aleph
|
||||
).
|
||||
|
||||
%% Unified interface: single verse
|
||||
test(binyan_av_single, [nondet]) :-
|
||||
binyan_av(single_verse(ref(shemot, 20, 8)), _, _).
|
||||
|
||||
%% Unified interface: two verses
|
||||
test(binyan_av_two_unified, [nondet]) :-
|
||||
binyan_av(
|
||||
two_verses(ref(bereishit, 1, 1), ref(bereishit, 1, 27)),
|
||||
_,
|
||||
_
|
||||
).
|
||||
|
||||
%% Common principle extraction
|
||||
test(common_principle_from_list, [nondet]) :-
|
||||
common_principle(
|
||||
[ref(bereishit, 1, 1), ref(bereishit, 1, 27)],
|
||||
bet_resh_aleph,
|
||||
_
|
||||
).
|
||||
|
||||
:- end_tests(binyan_av_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULES 5-8: KLAL UFRAT
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(klal_ufrat_tests).
|
||||
|
||||
%% Rule 5: General then particular narrows
|
||||
test(klal_ufrat_narrows) :-
|
||||
klal_ufrat(
|
||||
general(fruit_trees),
|
||||
particular([olive, grape]),
|
||||
narrowed_to([olive, grape], from(fruit_trees))
|
||||
).
|
||||
|
||||
%% Rule 6: Particular then general expands
|
||||
test(prat_uklal_expands) :-
|
||||
prat_uklal(
|
||||
particular([sheep, cattle]),
|
||||
general(all_livestock),
|
||||
expanded_to(all_livestock, including([sheep, cattle]))
|
||||
).
|
||||
|
||||
%% Rule 7: General-particular-general yields similar
|
||||
test(klal_ufrat_uklal_similar) :-
|
||||
klal_ufrat_uklal(
|
||||
general(all_damage),
|
||||
particular([ox_damage, pit_damage, fire_damage]),
|
||||
general(all_damage),
|
||||
similar_to([ox_damage, pit_damage, fire_damage],
|
||||
within(all_damage, negligence_based_damage))
|
||||
).
|
||||
|
||||
%% Generic klal ufrat
|
||||
test(generic_klal_ufrat) :-
|
||||
klal_ufrat(
|
||||
general(any_category),
|
||||
particular(specific_thing),
|
||||
narrowed_to(specific_thing, from(any_category))
|
||||
).
|
||||
|
||||
%% Scope results
|
||||
test(scope_narrowed) :-
|
||||
scope_result(klal_then_prat, narrowed).
|
||||
|
||||
test(scope_expanded) :-
|
||||
scope_result(prat_then_klal, expanded).
|
||||
|
||||
test(scope_similar) :-
|
||||
scope_result(klal_prat_klal, similar).
|
||||
|
||||
:- end_tests(klal_ufrat_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULES 9-11: DAVAR YATZA
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(davar_yatza_tests).
|
||||
|
||||
%% Rule 9: Exception teaches about the general
|
||||
test(exception_teaches_general) :-
|
||||
davar_yatza_llamed(
|
||||
exception(chatat, blood_sprinkling_north),
|
||||
general(all_offerings),
|
||||
teaches(blood_sprinkling_north, applies_to_all(all_offerings))
|
||||
).
|
||||
|
||||
%% Generic rule 9
|
||||
test(generic_exception_teaches) :-
|
||||
davar_yatza_llamed(
|
||||
exception(item, some_law),
|
||||
general(category),
|
||||
teaches(some_law, applies_to_all(category))
|
||||
).
|
||||
|
||||
%% Rule 10: Same type reduces severity
|
||||
test(same_type_reduces) :-
|
||||
davar_yatza_toan_echad(
|
||||
exception(item, shared_law),
|
||||
general(category, shared_law),
|
||||
reduces(shared_law, for(category), because(item))
|
||||
).
|
||||
|
||||
%% Rule 11: Different type creates dual application
|
||||
test(different_type_dual_rules) :-
|
||||
davar_yatza_toan_acher(
|
||||
exception(metzora, outside_camp_procedure),
|
||||
general(tumah, standard_purification),
|
||||
dual_rules(metzora, follows(standard_purification), and(outside_camp_procedure))
|
||||
).
|
||||
|
||||
:- end_tests(davar_yatza_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULE 12: LAMED INYAN
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(lamed_inyan_tests).
|
||||
|
||||
%% "Lo tignov" in context of capital crimes = kidnapping
|
||||
test(lo_tignov_kidnapping) :-
|
||||
lamed_me_inyano(
|
||||
ref(shemot, 20, 15),
|
||||
context(capital_crimes_sequence),
|
||||
meaning(lo_tignov, refers_to(kidnapping), not(ordinary_theft))
|
||||
).
|
||||
|
||||
%% Context from surrounding verses (requires prev and next verse to exist)
|
||||
test(context_from_surrounding, [nondet]) :-
|
||||
lamed_me_inyano(
|
||||
ref(shemot, 20, 14),
|
||||
context(ref(shemot, 20, 13), ref(shemot, 20, 15)),
|
||||
meaning_from(context, ref(shemot, 20, 14))
|
||||
).
|
||||
|
||||
%% Lamed misofo: conclusion clarifies ambiguous topic
|
||||
test(conclusion_clarifies) :-
|
||||
lamed_misofo(
|
||||
ambiguous(topic),
|
||||
concludes_with(clarification),
|
||||
meaning(topic, clarified_by(clarification))
|
||||
).
|
||||
|
||||
%% Unified context_determines_meaning
|
||||
test(context_determines_surrounding, [nondet]) :-
|
||||
context_determines_meaning(
|
||||
ref(shemot, 20, 15),
|
||||
surrounding,
|
||||
meaning(lo_tignov, refers_to(kidnapping), not(ordinary_theft))
|
||||
).
|
||||
|
||||
:- end_tests(lamed_inyan_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% RULE 13: SHNEI KETUVIM
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(shnei_ketuvim_tests).
|
||||
|
||||
%% Domains in tension
|
||||
test(judgment_mercy_tension) :-
|
||||
domains_in_tension(judgment, mercy).
|
||||
|
||||
test(mercy_judgment_tension) :-
|
||||
domains_in_tension(mercy, judgment).
|
||||
|
||||
test(holiness_transgression_tension) :-
|
||||
domains_in_tension(holiness, transgression).
|
||||
|
||||
%% Two verses with roots in opposing domains contradict
|
||||
test(verses_contradict_detection, [nondet]) :-
|
||||
verses_contradict(V1, V2, domain_conflict(_, _)),
|
||||
V1 \= V2.
|
||||
|
||||
%% Resolving verse shares roots with both
|
||||
test(resolving_verse_found, [nondet]) :-
|
||||
resolving_verse(V1, V2, V3),
|
||||
V1 \= V3,
|
||||
V2 \= V3.
|
||||
|
||||
%% Shnei ketuvim unified interface — harmonized case
|
||||
test(shnei_ketuvim_harmonized, [nondet]) :-
|
||||
shnei_ketuvim(
|
||||
contradicting(V1, V2),
|
||||
harmonized_reading(V1, V2, _V3),
|
||||
reasoning(V1, contradicts(V2), resolved_by(_)),
|
||||
_
|
||||
).
|
||||
|
||||
:- end_tests(shnei_ketuvim_tests).
|
||||
@@ -1,4 +1,7 @@
|
||||
%% mitzvot_test.pl — Tests for the specification layer.
|
||||
%%
|
||||
%% Phase 3: Updated for full 613 mitzvot encoding.
|
||||
%% Numbering: Positive 1-248, Prohibition 249-613.
|
||||
|
||||
:- use_module(library(plunit)).
|
||||
:- use_module('../src/specification/mitzvot').
|
||||
@@ -8,41 +11,62 @@
|
||||
|
||||
:- begin_tests(mitzvot).
|
||||
|
||||
%% The specification has mitzvot
|
||||
test(mitzvot_exist) :-
|
||||
total_encoded(Count),
|
||||
Count > 0.
|
||||
%% The specification has exactly 613 mitzvot
|
||||
test(total_613) :-
|
||||
total_encoded(613).
|
||||
|
||||
%% The three categories exist
|
||||
%% The two categories exist
|
||||
test(positive_mitzvot_exist) :-
|
||||
mitzvah(_, positive, _, _).
|
||||
|
||||
test(prohibition_mitzvot_exist) :-
|
||||
mitzvah(_, prohibition, _, _).
|
||||
|
||||
test(belief_mitzvot_exist) :-
|
||||
mitzvah(_, belief, _, _).
|
||||
%% Category counts match Rambam
|
||||
test(positive_count) :-
|
||||
mitzvah_category_count(positive, 248).
|
||||
|
||||
%% The first mitzvah is know_hashem
|
||||
test(prohibition_count) :-
|
||||
mitzvah_category_count(prohibition, 365).
|
||||
|
||||
%% The first mitzvah is know_hashem (Rambam Positive #1)
|
||||
test(first_mitzvah) :-
|
||||
mitzvah(1, belief, know_hashem, always).
|
||||
mitzvah(1, positive, know_hashem, always).
|
||||
|
||||
%% Core beliefs
|
||||
test(unity_of_hashem) :-
|
||||
mitzvah(2, positive, unity_of_hashem, always).
|
||||
|
||||
test(love_hashem) :-
|
||||
mitzvah(3, positive, love_hashem, always).
|
||||
|
||||
test(fear_hashem) :-
|
||||
mitzvah(4, positive, fear_hashem, always).
|
||||
|
||||
%% Shabbat mitzvot exist
|
||||
test(shabbat_rest) :-
|
||||
mitzvah(154, positive, rest_on_shabbat, when(seventh_day)).
|
||||
|
||||
test(shabbat_no_work) :-
|
||||
mitzvah(155, prohibition, not_work_on_shabbat, when(seventh_day)).
|
||||
test(sanctify_shabbat) :-
|
||||
mitzvah(155, positive, sanctify_shabbat, when(seventh_day)).
|
||||
|
||||
%% The three halt conditions have their mitzvot
|
||||
%% (Prohibitions are numbered 249-613)
|
||||
test(no_other_gods) :-
|
||||
mitzvah(2, prohibition, no_other_gods, always).
|
||||
mitzvah(249, prohibition, no_other_gods, always).
|
||||
|
||||
test(no_murder) :-
|
||||
mitzvah(289, prohibition, not_murder, always).
|
||||
test(not_murder) :-
|
||||
mitzvah(461, prohibition, not_murder, always).
|
||||
|
||||
test(no_adultery) :-
|
||||
mitzvah(330, prohibition, not_commit_adultery, always).
|
||||
test(not_commit_adultery) :-
|
||||
mitzvah(491, prohibition, not_commit_adultery, always).
|
||||
|
||||
%% Additional halt-related
|
||||
test(not_make_idols) :-
|
||||
mitzvah(250, prohibition, not_make_idols, always).
|
||||
|
||||
test(maintain_boundaries) :-
|
||||
mitzvah(532, prohibition, maintain_boundaries, always).
|
||||
|
||||
%% Source references exist
|
||||
test(mitzvah_sources_exist) :-
|
||||
@@ -51,6 +75,48 @@ test(mitzvah_sources_exist) :-
|
||||
test(shabbat_source) :-
|
||||
mitzvah_source(154, ref(shemot, 20, 8)).
|
||||
|
||||
test(murder_source) :-
|
||||
mitzvah_source(461, ref(shemot, 20, 13)).
|
||||
|
||||
%% Korbanot
|
||||
test(olah_exists) :-
|
||||
mitzvah(64, positive, bring_olah, when(offering_required)).
|
||||
|
||||
test(chatat_exists) :-
|
||||
mitzvah(65, positive, bring_chatat, when(unintentional_sin)).
|
||||
|
||||
%% Agriculture
|
||||
test(bikurim_exists) :-
|
||||
mitzvah(125, positive, bring_bikurim, when(first_fruits_available)).
|
||||
|
||||
test(shmitah_exists) :-
|
||||
mitzvah(122, positive, let_land_rest_shmitah, when(seventh_year)).
|
||||
|
||||
%% Justice
|
||||
test(appoint_judges) :-
|
||||
mitzvah(165, positive, appoint_judges, always).
|
||||
|
||||
test(not_accept_bribe) :-
|
||||
mitzvah(440, prohibition, judge_not_accept_bribe, always).
|
||||
|
||||
%% Interpersonal
|
||||
test(love_fellow) :-
|
||||
mitzvah(192, positive, love_fellow_jew, always).
|
||||
|
||||
test(not_gossip) :-
|
||||
mitzvah(472, prohibition, not_gossip, always).
|
||||
|
||||
%% Kashrut
|
||||
test(not_eat_blood) :-
|
||||
mitzvah(561, prohibition, not_eat_blood, always).
|
||||
|
||||
test(not_eat_meat_milk) :-
|
||||
mitzvah(564, prohibition, not_eat_meat_and_milk, always).
|
||||
|
||||
%% Last mitzvah
|
||||
test(last_mitzvah) :-
|
||||
mitzvah(613, prohibition, not_eat_sanctified_that_became_tamei, when(offering)).
|
||||
|
||||
:- end_tests(mitzvot).
|
||||
|
||||
|
||||
@@ -105,13 +171,13 @@ test(kadash_gematria) :-
|
||||
|
||||
:- begin_tests(relationships).
|
||||
|
||||
%% Tensions exist
|
||||
%% Tensions exist (updated IDs for Phase 3 numbering)
|
||||
test(justice_mercy_tension) :-
|
||||
mitzvah_conflicts_with(179, 295, _).
|
||||
mitzvah_conflicts_with(178, 489, _).
|
||||
|
||||
%% Complementary mitzvot
|
||||
test(complementary) :-
|
||||
complementary_mitzvot(1, 3).
|
||||
complementary_mitzvot(1, 2).
|
||||
|
||||
%% Root consonant sharing
|
||||
test(consonant_sharing) :-
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
%% phase3_verify_test.pl — Phase 3 verification tests.
|
||||
%%
|
||||
%% Architecture §4, Step 20: Verify the system can:
|
||||
%% 1. Deliberate a case through full dialectical process
|
||||
%% 2. Produce majority decision with preserved dissent
|
||||
%% 3. Apply middot-based reasoning
|
||||
%% 4. Run diagnostic protocol
|
||||
%% 5. Query 613 mitzvot by domain, condition, category
|
||||
|
||||
:- use_module(library(plunit)).
|
||||
:- use_module('../src/reasoning/interpret').
|
||||
:- use_module('../src/reasoning/challenge').
|
||||
:- use_module('../src/reasoning/resolve').
|
||||
:- use_module('../src/reasoning/teiku').
|
||||
:- use_module('../src/specification/mitzvot').
|
||||
:- use_module('../src/specification/torah_text').
|
||||
:- use_module('../src/specification/relationships').
|
||||
:- use_module('../src/specification/root_meanings').
|
||||
:- use_module('../src/middot/middot').
|
||||
:- use_module('../src/middot/kal_vachomer').
|
||||
:- use_module('../src/middot/gezerah_shavah').
|
||||
:- use_module('../src/middot/shnei_ketuvim').
|
||||
:- use_module('../src/diagnostic/tzaraat').
|
||||
:- use_module('../src/diagnostic/inspection').
|
||||
:- use_module('../src/diagnostic/diagnosis').
|
||||
|
||||
%% ============================================================
|
||||
%% STEP 20: FULL DELIBERATION CYCLE
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(full_deliberation).
|
||||
|
||||
%% A case about holiness can be interpreted
|
||||
test(interpret_holiness, [nondet]) :-
|
||||
Case = case(verify_holiness, holiness, [qof_dalet_shin],
|
||||
'What does it mean to be holy?'),
|
||||
interpret(Case, interpretation(verify_holiness, _, _, _, _)).
|
||||
|
||||
%% A case about judgment produces a challenge
|
||||
test(judgment_case_challenged, [nondet]) :-
|
||||
Case = case(verify_judgment, judgment, [shin_pe_tet, tzade_dalet_qof],
|
||||
'How to judge righteously?'),
|
||||
interpret(Case, Interpretation),
|
||||
challenge(Interpretation, kushya(_, _, _)).
|
||||
|
||||
%% A case can go through full resolution
|
||||
test(full_resolve_cycle, [nondet]) :-
|
||||
Case = case(verify_resolve, holiness, [qof_dalet_shin],
|
||||
'What is the holiness obligation?'),
|
||||
resolve(Case, Resolution),
|
||||
( Resolution = accepted(_)
|
||||
; Resolution = challenged(_, _)
|
||||
; Resolution = synthesized(_, _, _)
|
||||
; Resolution = teiku(_)
|
||||
).
|
||||
|
||||
%% Teiku count is tracked
|
||||
test(teiku_tracking) :-
|
||||
teiku_count(Count),
|
||||
integer(Count).
|
||||
|
||||
:- end_tests(full_deliberation).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% STEP 20: 613 MITZVOT QUERYABILITY
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(mitzvot_queryability).
|
||||
|
||||
%% Query all mitzvot in a domain
|
||||
test(query_by_domain, [nondet]) :-
|
||||
domain_mitzvot(judgment, Mitzvot),
|
||||
Mitzvot \= [].
|
||||
|
||||
%% Query mitzvot by category
|
||||
test(query_positives) :-
|
||||
findall(ID, mitzvah(ID, positive, _, _), IDs),
|
||||
length(IDs, 248).
|
||||
|
||||
test(query_prohibitions) :-
|
||||
findall(ID, mitzvah(ID, prohibition, _, _), IDs),
|
||||
length(IDs, 365).
|
||||
|
||||
%% Query conditional mitzvot
|
||||
test(query_conditional, [nondet]) :-
|
||||
mitzvah(_, _, _, when(_)).
|
||||
|
||||
%% Query unconditional mitzvot
|
||||
test(query_unconditional, [nondet]) :-
|
||||
mitzvah(_, _, _, always).
|
||||
|
||||
%% Mitzvah source grounding
|
||||
test(sources_exist) :-
|
||||
findall(ID, mitzvah_source(ID, _), IDs),
|
||||
length(IDs, Count),
|
||||
Count > 50. %% At least 50 mitzvot have sources
|
||||
|
||||
%% Complementary pairs exist
|
||||
test(complementary_pairs) :-
|
||||
findall(pair(A,B), complementary_mitzvot(A, B), Pairs),
|
||||
length(Pairs, Count),
|
||||
Count >= 16. %% 8 pairs * 2 directions
|
||||
|
||||
%% Tension pairs exist
|
||||
test(tension_pairs) :-
|
||||
findall(pair(A,B), mitzvah_conflicts_with(A, B, _), Pairs),
|
||||
length(Pairs, Count),
|
||||
Count >= 8.
|
||||
|
||||
:- end_tests(mitzvot_queryability).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% STEP 20: MIDDOT APPLICATION
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(middot_application).
|
||||
|
||||
%% All 13 middot are enumerated
|
||||
test(all_13_enumerated) :-
|
||||
all_middot(M),
|
||||
length(M, 13).
|
||||
|
||||
%% Kal vachomer produces derivation
|
||||
test(kal_vachomer_derivation) :-
|
||||
kal_vachomer(shabbat_rest, festival_rest, Derived, definite),
|
||||
Derived = derived(rest_obligation, from(shabbat), to(festival), kal_vachomer).
|
||||
|
||||
%% Gezerah shavah finds verbal link
|
||||
test(gezerah_shavah_link) :-
|
||||
gezerah_shavah(shabbat_keeping, pesach_keeping, _, shin_mem_resh).
|
||||
|
||||
%% Gezerah shavah from Torah text
|
||||
test(dynamic_verbal_link, [nondet]) :-
|
||||
shared_keyword(ref(bereishit, 1, 1), ref(bereishit, 1, 27), bet_resh_aleph).
|
||||
|
||||
%% Shnei ketuvim: domain tensions known
|
||||
test(domain_tensions_known) :-
|
||||
domains_in_tension(judgment, mercy),
|
||||
domains_in_tension(holiness, transgression).
|
||||
|
||||
%% Challenge module has middot-based strategies
|
||||
test(challenge_has_kal_vachomer_strategy) :-
|
||||
challenge_strength(contradiction(kal_vachomer_tension, _, _, _), strong).
|
||||
|
||||
test(challenge_has_shnei_ketuvim_strategy) :-
|
||||
challenge_strength(contradiction(shnei_ketuvim_tension, _, _, _), strong).
|
||||
|
||||
:- end_tests(middot_application).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% STEP 20: TZARA'AT DIAGNOSTIC
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(tzaraat_diagnostic).
|
||||
|
||||
%% Clean input passes
|
||||
test(clean_input_passes) :-
|
||||
diagnose(input(declared, [visible], within_bounds, []), declared_tahor).
|
||||
|
||||
%% Impure input rejected
|
||||
test(impure_input_rejected) :-
|
||||
diagnose(input(undeclared, [visible], within_bounds, []), confirmed_tamei).
|
||||
|
||||
%% Ambiguous input quarantined
|
||||
test(ambiguous_input_quarantined) :-
|
||||
diagnose(input(declared, [hidden], within_bounds, []), requires_quarantine(quarantine_1)).
|
||||
|
||||
%% The paradox: full visibility = purity
|
||||
test(full_visibility_paradox) :-
|
||||
diagnose(
|
||||
input(undeclared, [hidden], exceeds_bounds, [leaks_implementation]),
|
||||
fully_visible_tahor
|
||||
).
|
||||
|
||||
%% 8 diagnosis states
|
||||
test(eight_states) :-
|
||||
findall(S, diagnosis_state(S), States),
|
||||
length(States, 8).
|
||||
|
||||
:- end_tests(tzaraat_diagnostic).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% STEP 20: ROOT AND VERSE QUERYABILITY
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(root_verse_queries).
|
||||
|
||||
%% All semantic domains
|
||||
test(domains_exist) :-
|
||||
all_domains(Domains),
|
||||
length(Domains, Count),
|
||||
Count >= 10.
|
||||
|
||||
%% Roots in a domain
|
||||
test(roots_in_holiness, [nondet]) :-
|
||||
roots_in_domain(holiness, Roots),
|
||||
Roots \= [].
|
||||
|
||||
%% Verses mentioning a root
|
||||
test(verses_with_kadosh, [nondet]) :-
|
||||
verses_mentioning_root(qof_dalet_shin, Verses),
|
||||
Verses \= [].
|
||||
|
||||
%% Verse roots can be retrieved
|
||||
test(verse_roots_retrieved) :-
|
||||
verse_roots(bereishit, 1, 1, Roots),
|
||||
member(bet_resh_aleph, Roots).
|
||||
|
||||
:- end_tests(root_verse_queries).
|
||||
@@ -0,0 +1,202 @@
|
||||
%% tzaraat_test.pl — Tests for the Tzara'at diagnostic protocol.
|
||||
%%
|
||||
%% Phase 3, Step 19: Multi-stage input validation.
|
||||
|
||||
:- use_module(library(plunit)).
|
||||
:- use_module('../src/diagnostic/tzaraat').
|
||||
:- use_module('../src/diagnostic/diagnosis').
|
||||
:- use_module('../src/diagnostic/inspection').
|
||||
:- use_module('../src/diagnostic/quarantine').
|
||||
|
||||
%% ============================================================
|
||||
%% DIAGNOSIS STATE TESTS
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(diagnosis_states).
|
||||
|
||||
%% All 8 states exist
|
||||
test(all_states_exist) :-
|
||||
findall(S, diagnosis_state(S), States),
|
||||
length(States, 8).
|
||||
|
||||
%% Terminal states
|
||||
test(tamei_is_terminal) :-
|
||||
terminal_state(confirmed_tamei).
|
||||
|
||||
test(tahor_is_terminal) :-
|
||||
terminal_state(declared_tahor).
|
||||
|
||||
test(fully_visible_is_terminal) :-
|
||||
terminal_state(fully_visible_tahor).
|
||||
|
||||
%% Initial state
|
||||
test(initial_state_is_inspection) :-
|
||||
initial_state(initial_inspection).
|
||||
|
||||
%% Valid transitions
|
||||
test(initial_to_quarantine) :-
|
||||
valid_transition(initial_inspection, quarantine_1).
|
||||
|
||||
test(initial_to_tamei) :-
|
||||
valid_transition(initial_inspection, confirmed_tamei).
|
||||
|
||||
test(initial_to_tahor) :-
|
||||
valid_transition(initial_inspection, declared_tahor).
|
||||
|
||||
test(initial_to_fully_visible) :-
|
||||
valid_transition(initial_inspection, fully_visible_tahor).
|
||||
|
||||
test(quarantine_1_to_reinspection) :-
|
||||
valid_transition(quarantine_1, reinspection_1).
|
||||
|
||||
test(quarantine_2_to_final_reinspection) :-
|
||||
valid_transition(quarantine_2, reinspection_2).
|
||||
|
||||
%% Transition reasons exist
|
||||
test(transition_has_reason) :-
|
||||
transition_reason(initial_inspection, quarantine_1, Reason),
|
||||
Reason \= ''.
|
||||
|
||||
:- end_tests(diagnosis_states).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% INSPECTION TESTS
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(inspection_tests).
|
||||
|
||||
%% Clean input → declared tahor
|
||||
test(clean_input_tahor) :-
|
||||
Input = input(declared, [visible, visible], within_bounds, []),
|
||||
inspect(Input, declared_tahor).
|
||||
|
||||
%% Undeclared source → confirmed tamei (high severity)
|
||||
test(undeclared_source_tamei) :-
|
||||
Input = input(undeclared, [visible], within_bounds, []),
|
||||
inspect(Input, confirmed_tamei).
|
||||
|
||||
%% Hidden dependency only → quarantine (moderate severity)
|
||||
test(hidden_dep_quarantine) :-
|
||||
Input = input(declared, [hidden], within_bounds, []),
|
||||
inspect(Input, quarantine_1).
|
||||
|
||||
%% Scope creep → quarantine (moderate severity)
|
||||
test(scope_creep_quarantine) :-
|
||||
Input = input(declared, [visible], exceeds_bounds, []),
|
||||
inspect(Input, quarantine_1).
|
||||
|
||||
%% The paradox: ALL signs present → fully visible tahor
|
||||
test(fully_visible_paradox) :-
|
||||
Input = input(undeclared, [hidden], exceeds_bounds, [leaks_implementation]),
|
||||
inspect(Input, fully_visible_tahor).
|
||||
|
||||
%% Low severity only → declared tahor
|
||||
test(low_severity_tahor) :-
|
||||
Input = input(declared, [visible], within_bounds, [leaks_implementation]),
|
||||
inspect(Input, declared_tahor).
|
||||
|
||||
%% Sign detection
|
||||
test(detect_undeclared_source) :-
|
||||
has_sign(input(undeclared, [], within_bounds, []), undeclared_source).
|
||||
|
||||
test(detect_hidden_dependency) :-
|
||||
has_sign(input(declared, [hidden], within_bounds, []), hidden_dependency).
|
||||
|
||||
test(detect_scope_creep) :-
|
||||
has_sign(input(declared, [], exceeds_bounds, []), scope_creep).
|
||||
|
||||
test(detect_exposed_internals) :-
|
||||
has_sign(input(declared, [], within_bounds, [leaks_implementation]), exposed_internals).
|
||||
|
||||
%% Sign count
|
||||
test(clean_has_zero_signs) :-
|
||||
count_signs(input(declared, [visible], within_bounds, []), 0).
|
||||
|
||||
test(all_signs_count_four) :-
|
||||
count_signs(input(undeclared, [hidden], exceeds_bounds, [leaks_implementation]), 4).
|
||||
|
||||
:- end_tests(inspection_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% QUARANTINE TESTS
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(quarantine_tests).
|
||||
|
||||
%% Can quarantine an input
|
||||
test(quarantine_creates_record,
|
||||
[cleanup(retractall(quarantine:quarantine_record(_, _, _, _)))]) :-
|
||||
retractall(quarantine:quarantine_record(_, _, _, _)),
|
||||
Input = input(declared, [hidden], within_bounds, []),
|
||||
quarantine_input(test_q1, Input, quarantine_1),
|
||||
quarantine:quarantine_record(test_q1, quarantine_1, Signs, 1),
|
||||
member(hidden_dependency, Signs).
|
||||
|
||||
%% Reinspection: signs cleared → tahor
|
||||
test(reinspect_cleared_tahor,
|
||||
[cleanup(retractall(quarantine:quarantine_record(_, _, _, _)))]) :-
|
||||
retractall(quarantine:quarantine_record(_, _, _, _)),
|
||||
Input1 = input(declared, [hidden], within_bounds, []),
|
||||
quarantine_input(test_r1, Input1, quarantine_1),
|
||||
%% After quarantine, input is clean
|
||||
Input2 = input(declared, [visible], within_bounds, []),
|
||||
reinspect(test_r1, Input2, declared_tahor).
|
||||
|
||||
%% Reinspection: signs spread → tamei
|
||||
test(reinspect_spread_tamei,
|
||||
[cleanup(retractall(quarantine:quarantine_record(_, _, _, _)))]) :-
|
||||
retractall(quarantine:quarantine_record(_, _, _, _)),
|
||||
Input1 = input(declared, [hidden], within_bounds, []),
|
||||
quarantine_input(test_r2, Input1, quarantine_1),
|
||||
%% After quarantine, more problems appeared
|
||||
Input2 = input(declared, [hidden], exceeds_bounds, [leaks_implementation]),
|
||||
reinspect(test_r2, Input2, confirmed_tamei).
|
||||
|
||||
:- end_tests(quarantine_tests).
|
||||
|
||||
|
||||
%% ============================================================
|
||||
%% TZARA'AT MASTER MODULE TESTS
|
||||
%% ============================================================
|
||||
|
||||
:- begin_tests(tzaraat_master).
|
||||
|
||||
%% Clean input diagnosed immediately
|
||||
test(diagnose_clean) :-
|
||||
Input = input(declared, [visible], within_bounds, []),
|
||||
diagnose(Input, declared_tahor).
|
||||
|
||||
%% Impure input diagnosed immediately
|
||||
test(diagnose_impure) :-
|
||||
Input = input(undeclared, [visible], within_bounds, []),
|
||||
diagnose(Input, confirmed_tamei).
|
||||
|
||||
%% Ambiguous input requires quarantine
|
||||
test(diagnose_ambiguous) :-
|
||||
Input = input(declared, [hidden], within_bounds, []),
|
||||
diagnose(Input, requires_quarantine(quarantine_1)).
|
||||
|
||||
%% Full diagnostic flow: clean input
|
||||
test(full_flow_clean) :-
|
||||
Input = input(declared, [visible], within_bounds, []),
|
||||
full_diagnostic_flow(flow_clean, [Input], declared_tahor).
|
||||
|
||||
%% Full diagnostic flow: immediate tamei
|
||||
test(full_flow_tamei) :-
|
||||
Input = input(undeclared, [visible], within_bounds, []),
|
||||
full_diagnostic_flow(flow_tamei, [Input], confirmed_tamei).
|
||||
|
||||
%% Full diagnostic flow: fully visible paradox
|
||||
test(full_flow_paradox) :-
|
||||
Input = input(undeclared, [hidden], exceeds_bounds, [leaks_implementation]),
|
||||
full_diagnostic_flow(flow_paradox, [Input], fully_visible_tahor).
|
||||
|
||||
%% Full diagnostic flow: quarantine then cleared
|
||||
test(full_flow_quarantine_cleared, [cleanup(retractall(quarantine_record(_, _, _, _)))]) :-
|
||||
Input1 = input(declared, [hidden], within_bounds, []),
|
||||
Input2 = input(declared, [visible], within_bounds, []),
|
||||
full_diagnostic_flow(flow_q_clear, [Input1, Input2], declared_tahor).
|
||||
|
||||
:- end_tests(tzaraat_master).
|
||||
Reference in new issue
Block a user