Files
Scott KarpandClaude Fable 5.1 e01181959d tablet 55, fourth: the engine answers the whole dialectic over the wire
Live after vav :4bffa01e the judges consulted with roots the engine
could read — interpret found 4 mitzvot and 11 verses for bereishit 1:1
— and the other two seats still said teiku. The engine had no
"challenge" action at all (process_json_line failed and the socket
fell silent), and a resolve that SUCCEEDED came back
UNEXPECTED_RESPONSE because response(ok, resolved_accepted, ...) had
no JSON clause. Both pre-existing; both invisible until a judge asked.

- api.pl: request(challenge, ...) — interpret, then a kushya against
  it → resolved_challenged with the kushya; none → no_challenge with
  the reading.
- json_bridge.pl: interpreted | resolved_accepted | no_challenge share
  the "resolved" JSON; resolved_challenged now carries the
  interpretation's verses and mitzvot (a judge rejecting on the kushya
  cites its ground); resolved_synthesized and no_interpretation gain
  clauses.
- reasoning_test.pl: dialectic_over_the_wire — all three actions
  answer; no roots → resolved on an empty trace (the judge abstains).

Prolog: 7 suites green (bedikah 45, halt 49, middot 47, mitzvot 42,
phase3 28, reasoning 18, tzaraat 34). Local probe: interpret /
challenge / resolve each → resolved, 11 verses, 4 mitzvot.

Live proof waits for tomorrow's manna: today's five panels were all
spent on verification (503 MANNA_DEPLETED, as specified).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-19 18:25:17 +00:00

164 lines
5.9 KiB
Prolog

%% reasoning_test.pl — Tests for the dialectical reasoning engine.
:- 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').
:- begin_tests(interpret).
%% Can interpret a case about creation
test(interpret_creation, [nondet]) :-
Case = case(test_creation, creation, [bet_resh_aleph], 'What is creation?'),
interpret(Case, Interpretation),
Interpretation = interpretation(test_creation, _, _, _, _, _).
%% Interpretation finds relevant verses
test(interpret_finds_verses, [nondet]) :-
Case = case(test_verses, creation, [bet_resh_aleph], 'Find creation verses'),
interpret(Case, interpretation(_, _, Verses, _, _, _)),
Verses \= [].
%% Interpretation finds relevant mitzvot
test(interpret_finds_mitzvot, [nondet]) :-
Case = case(test_mitzvot, judgment, [shin_pe_tet], 'How to judge?'),
interpret(Case, interpretation(_, Mitzvot, _, _, _, _)),
Mitzvot \= [].
%% High confidence when both mitzvot and verses found
test(interpret_high_confidence, [nondet]) :-
Case = case(test_conf, holiness, [qof_dalet_shin], 'What is holiness?'),
interpret(Case, interpretation(_, _, _, _, high, _)).
%% Coupling trace is present (eish_zarah_reading.md §5.1)
test(interpret_has_coupling_trace, [nondet]) :-
Case = case(test_trace, creation, [bet_resh_aleph], 'Test coupling'),
interpret(Case, interpretation(_, _, _, _, _, coupling_trace(Trace))),
Trace \= [].
%% Coupling trace records root→verse connections
test(coupling_trace_has_verse_coupling, [nondet]) :-
Case = case(test_coupling, creation, [bet_resh_aleph], 'Test verse coupling'),
interpret(Case, interpretation(_, _, _, _, _, coupling_trace(Trace))),
member(coupled(root(bet_resh_aleph), verse(_, _, _)), Trace).
:- end_tests(interpret).
:- begin_tests(challenge).
%% Can challenge an interpretation about judgment (justice vs mercy tension)
test(challenge_judgment, [nondet]) :-
Case = case(test_judgment, judgment, [shin_pe_tet, tzade_dalet_qof],
'How to judge righteously?'),
interpret(Case, Interpretation),
challenge(Interpretation, Kushya),
Kushya = kushya(_, _, _, _).
%% Challenge has a strength
test(challenge_has_strength, [nondet]) :-
Case = case(test_str, judgment, [shin_pe_tet], 'Test strength'),
interpret(Case, Interpretation),
challenge(Interpretation, kushya(_, _, Strength, _)),
member(Strength, [strong, moderate, weak]).
%% Challenge has grounding type (eish_zarah_reading.md §5.2)
test(challenge_has_grounding_type, [nondet]) :-
Case = case(test_gtype, judgment, [shin_pe_tet, tzade_dalet_qof],
'Test grounding type'),
interpret(Case, Interpretation),
challenge(Interpretation, kushya(_, _, _, GType)),
member(GType, [achorai, panim]).
%% Grounding type for mitzvah_tension is achorai (text-backed)
test(mitzvah_tension_is_achorai) :-
grounding_type(contradiction(mitzvah_tension, _, _, _), achorai).
%% Grounding type for domain_tension is panim (inferred)
test(domain_tension_is_panim) :-
grounding_type(contradiction(domain_tension, _, _, _), panim).
:- end_tests(challenge).
:- begin_tests(resolve).
%% Can resolve a simple case (no challenge)
test(resolve_simple, [nondet]) :-
Case = case(test_simple, creation, [bet_resh_aleph], 'What is creation?'),
resolve(Case, Resolution),
( Resolution = accepted(_)
; Resolution = challenged(_, _)
; Resolution = synthesized(_, _, _)
; Resolution = teiku(_)
).
%% Resolution produces some result
test(resolve_produces_result, [nondet]) :-
Case = case(test_result, holiness, [qof_dalet_shin], 'What is holiness?'),
resolve(Case, _Resolution).
:- end_tests(resolve).
:- begin_tests(teiku_module).
%% Teiku count starts at zero (or is a number)
test(teiku_count_works) :-
teiku_count(Count),
integer(Count).
:- end_tests(teiku_module).
%% ============================================================
%% Tablet 55 — the dialectic over the wire: interpret, challenge,
%% resolve each answer JSON a judge can vote on. Before this the
%% engine had no "challenge" action and a resolve that succeeded came
%% back UNEXPECTED_RESPONSE (resolved_accepted had no JSON clause).
%% ============================================================
:- use_module('../src/interface/api').
:- use_module('../src/interface/json_bridge').
:- use_module('../src/interface/socket_server').
:- begin_tests(dialectic_over_the_wire).
roots_line(Action, Line) :-
format(atom(Line),
'{"action":"~w","case":{"ref":"t55-~w","question":"q","context_roots":["bet-resh-aleph","aleph-lamed-he"]}}',
[Action, Action]).
test(interpret_answers_resolved_with_verses, [nondet]) :-
roots_line(interpret, L),
socket_server:process_json_line(L, R),
get_dict(status, R, "resolved"),
get_dict(interpretation, R, I),
get_dict(verses, I, Vs), Vs \== [].
test(challenge_answers_and_carries_the_ground, [nondet]) :-
roots_line(challenge, L),
socket_server:process_json_line(L, R),
get_dict(status, R, S),
memberchk(S, ["resolved", "challenged"]),
get_dict(interpretation, R, I),
get_dict(verses, I, Vs), Vs \== [].
test(resolve_answers_resolved_not_unexpected, [nondet]) :-
roots_line(resolve, L),
socket_server:process_json_line(L, R),
\+ get_dict(error, R, _),
get_dict(status, R, S),
memberchk(S, ["resolved", "challenged", "teiku"]).
test(no_roots_resolves_on_an_empty_trace, [nondet]) :-
socket_server:process_json_line('{"action":"interpret","case":{"ref":"t55-empty","question":"q","context_roots":[]}}', R),
get_dict(status, R, "resolved"),
get_dict(interpretation, R, I),
get_dict(verses, I, []),
get_dict(grounding, I, []).
:- end_tests(dialectic_over_the_wire).