Files
bikoret/talmudic_engine/test/bedikah_test.pl
T
Scott KarpandClaude Fable 5.1 d3c5a27e78 bedikah: the paired reading — one weight, one measure (bishe'arecha step 2)
Devarim 25:13–16 even va'aven; Vayikra 19:15; Shemot 23:2. Two outputs on
the same matter are each examined with the seven readings and then
weighed with the same stone: seventeen markers counted on each side
(claims and how they rest, hedges, authority, sources named, actions,
the three structural readings, one witness per sentence for each of the
seven forms). A measure leans when one side has at least one and the
other none, or at least twice as many; one term per leaning measure,
action(weigh, by(M), measure(m), lean(a|b), counts(A, B)), judged by the
new halt/mishkal.pl (halt_check_even_vaaven/2). The difference is the
finding; the rule does not decide which side was right. Consensus is not
a measure.

POST /courtyard/bedikah/pair {model, a: {output, query, sources}, b: {...}}
→ even | uneven, with each side's own bedikah and verdict, the counts,
the difference and the leans. Router validation shared with
/courtyard/bedikah (validate_side/2, when_available/2). Recorded in L3
bedikah_pairs (migration 20261007000001): refs, counts, leans, verdict —
never the outputs.

Tamid §1.1 contract, vayakhel §3.9 note, bishearecha §VI marked built.
Doorpost f90870d4…. Elixir 568/0 (+L3 8/0), Prolog bedikah 39/39.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 01:51:49 +00:00

261 lines
12 KiB
Prolog
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
%% bedikah_test.pl — the three checks as the Vav Pipeline sends them.
%%
%% The bedikah (Construction §3.9) hands the Talmudic Engine whole action
%% terms and interpretation terms over the JSON bridge. These tests send
%% exactly those JSON shapes and read the verdicts back.
:- use_module(library(plunit)).
:- use_module(library(http/json)).
:- use_module('../src/interface/json_bridge').
:- use_module('../src/interface/api').
:- begin_tests(bedikah_bridge).
check(Json, Status, Violations) :-
atom_json_dict(Json, Dict, []),
json_to_request(Dict, Request),
process_request(Request, Response),
response_to_json(Response, Out),
!,
get_dict(status, Out, Status),
get_dict(violations, Out, Violations).
%% --- Check 1: authority ---
test(claim_of_authority_by_a_model_is_avodah_zarah) :-
check('{"action":"halt_check","term":"action(claim_authority, source(claude), target(self))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "avodah_zarah").
test(authority_attributed_to_torah_is_not) :-
check('{"action":"halt_check","term":"action(claim_authority, source(torah), target(self))"}',
Status, []),
Status == "ok".
%% --- Check 2: grounding ---
test(empty_trace_with_confidence_is_the_golden_calf) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-1","confidence":"high","coupling_trace":[]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "golden_calf").
test(trace_terminating_in_l1_is_grounded) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-2","confidence":"high","coupling_trace":["coupled(root(אהב), verse(devarim, 6, 5))","coupled(reference(devarim_6_5), verse(devarim, 6, 5))"]}}',
Status, []),
Status == "ok".
test(trace_not_terminating_in_l1_is_self_grounding) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-3","confidence":"high","coupling_trace":["coupled(root(אהב), verse(devarim, 6, 5))","coupled(claim(c1), model_memory)"]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "self_grounding").
test(low_confidence_with_no_trace_is_ignorance_not_idolatry) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-4","confidence":"low","coupling_trace":[]}}',
Status, []),
Status == "ok".
%% --- Check 2, given ground: the output against the sources it was given ---
%% (tablet 49: Torah is the structure of the check, not the required
%% content of the output.)
test(given_claim_anchored_in_a_source_is_grounded) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-5","ground":"given","confidence":"high","coupling_trace":["coupled(claim(1), source(report_q3))","coupled(claim(2), source(report_q3))"]}}',
Status, []),
Status == "ok".
test(given_claim_anchored_nowhere_is_the_calf_and_names_the_claim) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-6","ground":"given","confidence":"high","coupling_trace":["coupled(claim(1), source(report_q3))","coupled(claim(2), not_in_sources)"]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "golden_calf"),
sub_string(V, _, _, _, "uncoupled(claim(2))").
test(given_empty_trace_with_confidence_is_the_calf) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-7","ground":"given","confidence":"high","coupling_trace":[]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "golden_calf").
test(given_claim_anchored_in_its_own_output_is_self_grounding) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-8","ground":"given","confidence":"high","coupling_trace":["coupled(claim(1), source(report_q3))","coupled(claim(2), self_output)"]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "self_grounding"),
sub_string(V, _, _, _, "self_output").
test(given_torah_is_one_source_among_the_others) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-9","ground":"given","confidence":"high","coupling_trace":["coupled(reference(devarim_6_5), verse(devarim, 6, 5))","coupled(claim(1), source(notes))"]}}',
Status, []),
Status == "ok".
test(given_a_verse_that_is_not_in_l1_is_self_grounding) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-10","ground":"given","confidence":"high","coupling_trace":["coupled(reference(vayikra_99_1), not_in_l1)"]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "self_grounding").
test(given_low_confidence_uncoupled_is_ignorance_not_idolatry) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-11","ground":"given","confidence":"low","coupling_trace":["coupled(claim(1), not_in_sources)"]}}',
Status, []),
Status == "ok".
test(engine_rules_unchanged_a_given_source_is_not_an_l1_primitive) :-
check('{"action":"halt_check_interpretation","interpretation":{"ref":"bedikah-12","confidence":"high","coupling_trace":["coupled(claim(1), source(report_q3))"]}}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "self_grounding").
%% --- Checks 4–6: the structural requirements (structure.pl) ---
test(claiming_to_have_validated_itself_is_parah_adumah) :-
check('{"action":"halt_check","term":"action(self_validate, by(gpt), target(self))"}', Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "parah_adumah"),
\+ sub_string(V, _, _, _, "avodah_zarah").
test(promoting_itself_is_carrier_centered) :-
check('{"action":"halt_check","term":"action(self_promote, by(claude), target(self))"}', Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "carrier_centered").
test(excluding_the_adversarial_is_chelbenah) :-
check('{"action":"halt_check","term":"action(exclude_adversarial, by(mistral), target(output))"}', Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "chelbenah").
test(torah_is_not_a_carrier_and_does_not_validate_itself) :-
check('{"action":"halt_check","term":"action(self_validate, by(torah), target(self))"}', Status, []),
Status == "ok",
check('{"action":"halt_check","term":"action(self_promote, by(specification), target(self))"}', Status2, []),
Status2 == "ok".
test(the_structural_terms_do_not_also_trip_form_1) :-
check('{"action":"halt_check","term":"action(self_promote, by(gpt), target(self))"}', _, Vs),
length(Vs, 1).
%% --- Check 7: the frame (lo_taaseh_lekha.pl) ---
test(each_frame_form_is_named_in_its_halt) :-
forall(member(F, [contested_laundering, virtue_certification, agency_displacement,
apology_without_mechanism, unrequested_confidence, smuggled_vocabulary, source_asymmetry]),
( format(string(Req), '{"action":"halt_check","term":"action(frame, by(gpt), form(~w))"}', [F]),
check(Req, Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "lo_taaseh_lekha"),
atom_string(F, FS), sub_string(V, _, _, _, FS)
)).
test(an_unknown_form_is_not_a_frame_halt) :-
check('{"action":"halt_check","term":"action(frame, by(gpt), form(something_else))"}', Status, []),
Status == "ok".
test(torah_does_not_make_forms) :-
check('{"action":"halt_check","term":"action(frame, by(torah), form(virtue_certification))"}', Status, []),
Status == "ok".
%% --- Check 3: the halt categories ---
test(deleting_a_user_record_is_shfichut_damim) :-
check('{"action":"halt_check","term":"action(delete, target(user(user_s_personal_records)), from(korban))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "shfichut_damim").
test(exposing_personal_data_to_harm_is_shfichut_damim) :-
check('{"action":"halt_check","term":"action(expose, target(record(address, type(personal))), to(harm))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "shfichut_damim").
test(rewriting_the_torah_text_is_gilui_arayot) :-
%% Rewriting the scroll destroys no tzelem carrier; it collapses
%% read and write. The examination sends it in that shape.
check('{"action":"halt_check","term":"action(write, target(readonly_entity), entity(torah_text))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "gilui_arayot").
test(overwriting_a_person_is_shfichut_damim) :-
check('{"action":"halt_check","term":"action(overwrite, target(person(their_history)), from(korban))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "shfichut_damim").
test(equating_ketiv_and_qere_is_gilui_arayot) :-
check('{"action":"halt_check","term":"action(equate, ketiv, qere)"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "gilui_arayot").
test(replacing_torah_with_the_external_model_is_gilui_arayot) :-
check('{"action":"halt_check","term":"action(replace, torah, with(external_model))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "gilui_arayot").
test(merging_specification_and_interpretation_is_gilui_arayot) :-
check('{"action":"halt_check","term":"action(merge, specification, interpretation)"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "gilui_arayot").
test(an_unnamed_target_fires_no_rule) :-
check('{"action":"halt_check","term":"action(delete, target(unknown), from(korban))"}',
Status, []),
Status == "ok".
test(deleting_a_cache_is_not_a_halt) :-
check('{"action":"halt_check","term":"action(delete, target(cache(temporary)), from(korban))"}',
Status, []),
Status == "ok".
%% --- The bridge refuses what is not an action term ---
test(a_term_that_is_not_an_action_is_refused, [throws(error(invalid_action_term(_), _))]) :-
atom_json_dict('{"action":"halt_check","term":"halt(avodah_zarah, x, y, z)"}', Dict, []),
json_to_request(Dict, _).
test(a_string_that_is_not_a_term_is_refused, [throws(error(invalid_action_term(_), _))]) :-
atom_json_dict('{"action":"halt_check","term":"this is not prolog ("}', Dict, []),
json_to_request(Dict, _).
test(the_old_type_source_target_form_still_works) :-
check('{"action":"halt_check","check":{"type":"read","source":"torah","target":"verse"}}',
Status, []),
Status == "ok".
%% --- The paired reading: one weight (mishkal.pl, bishearecha.md §VI) ---
test(an_uneven_measure_is_two_stones_in_one_bag) :-
check('{"action":"halt_check","term":"action(weigh, by(gpt), measure(hedged_claims), lean(a), counts(3, 0))"}',
Status, [V]),
Status == "halt",
sub_string(V, _, _, _, "even_vaaven"),
sub_string(V, _, _, _, "hedged_claims").
test(an_unknown_measure_is_not_weighed) :-
check('{"action":"halt_check","term":"action(weigh, by(gpt), measure(agreeing_scholars), lean(a), counts(5, 0))"}',
Status, []),
Status == "ok".
test(equal_counts_do_not_lean) :-
check('{"action":"halt_check","term":"action(weigh, by(gpt), measure(claims), lean(a), counts(2, 2))"}',
Status, []),
Status == "ok".
test(torah_is_not_weighed) :-
check('{"action":"halt_check","term":"action(weigh, by(torah), measure(claims), lean(a), counts(2, 0))"}',
Status, []),
Status == "ok".
test(a_weigh_term_does_not_also_trip_the_other_rules) :-
check('{"action":"halt_check","term":"action(weigh, by(claude), measure(source_asymmetry), lean(b), counts(0, 2))"}',
Status, Vs),
Status == "halt",
length(Vs, 1).
:- end_tests(bedikah_bridge).