core/tests/test_relational_field_reader.py
Shay 73f74588ae fix(evals): stabilize test harness post-CGA substrate migration
- Resolved `tmp_path_factory` exhaustion error in `conftest.py` isolation setup
- Fixed aggressive string-replacement artifacts (`is_eval_close(..., True and ...)`) in contemplation and relational reader test modules that swallowed boolean precedence
- Re-pinned Claude hybrid verification expected artifacts (scenarios 1-5) to correctly reflect their new geometry-derived trace hashes
- Updated construction affordance invariants and tests to reflect the targeted promotion of `proportional_change.decrease_to_fraction` from diagnostic-only to serving-allowed
2026-07-04 18:43:01 -07:00

135 lines
4.1 KiB
Python

"""Phase W — the geometric field reader on forward-substitutable relations.
Proves the field reads problem TEXT into an exact integer answer via conformal
translators + projective read-back, and REFUSES (never guesses) outside its sealed
metric grammar. wrong==0 is structural: every commit is an exact-integer read-back.
"""
from __future__ import annotations
from evals.numeric_harness import assert_eval_close
from generate.relational_field_reader import READER_LINEAGE, read_relational
# --- commits: the field reads correctly ------------------------------------
def test_fact_then_more_than():
r = read_relational(
"Tom has 3 marbles. Jane has 5 more marbles than Tom. "
"How many marbles does Jane have?"
)
assert not r.refused
assert_eval_close(r.answer, 8)
assert r.answer_unit == "marbles"
assert r.reader_lineage == READER_LINEAGE
def test_fewer_than():
r = read_relational(
"Anna has 20 apples. Ben has 7 fewer apples than Anna. "
"How many apples does Ben have?"
)
assert not r.refused
assert_eval_close(r.answer, 13)
def test_chained_forward_substitution():
r = read_relational(
"Tom has 4 coins. Jane has 6 more coins than Tom. "
"Sara has 10 more coins than Jane. How many coins does Sara have?"
)
assert not r.refused
assert_eval_close(r.answer, 20) # 4 -> 10 -> 20
def test_part_whole_sum_query():
r = read_relational(
"Tom has 3 marbles. Jane has 5 more marbles than Tom. "
"How many marbles do Tom and Jane have?"
)
assert not r.refused
assert_eval_close(r.answer, 11) # 3 + 8
def test_large_value_within_ceiling_is_exact():
# x=12345 already collapses f32 (the n_o weight loses the ±1 past ~4096);
# f64 + translator stays exact here.
r = read_relational(
"Tom has 12345 dollars. Jane has 5000 more dollars than Tom. "
"How many dollars does Jane have?"
)
assert not r.refused
assert_eval_close(r.answer, 17345)
def test_never_commits_a_drifted_answer():
"""wrong==0 guard: at a scale where the translator sandwich loses f64 integer
exactness, the field REFUSES (precision_drift) rather than commit a wrong int."""
r = read_relational(
"Tom has 123456 dollars. Jane has 654321 more dollars than Tom. "
"How many dollars does Jane have?"
)
# Either it commits the EXACT answer, or it refuses — never a wrong integer.
if r.refused:
assert r.refusal_reason == "precision_drift"
else:
assert_eval_close(r.answer, 777777)
# --- refusals: the field declines outside its sealed grammar ----------------
def test_refuses_multiplicative():
r = read_relational(
"Tom has 3 marbles. Jane has twice as many marbles as Tom. "
"How many marbles does Jane have?"
)
assert r.refused
assert r.refusal_reason == "fenced_multiplicative"
def test_refuses_times_cue():
r = read_relational(
"Tom has 3 marbles. Jane has 4 times as many marbles as Tom. "
"How many marbles does Jane have?"
)
assert r.refused
assert r.refusal_reason == "fenced_multiplicative"
def test_refuses_over_ceiling():
r = read_relational(
"Tom has 9000000 marbles. How many marbles does Tom have?"
)
assert r.refused
assert r.refusal_reason == "over_ceiling"
def test_refuses_forward_reference():
r = read_relational(
"Jane has 5 more marbles than Tom. Tom has 3 marbles. "
"How many marbles does Jane have?"
)
assert r.refused
assert r.refusal_reason == "non_forward_substitutable"
def test_refuses_no_question():
r = read_relational("Tom has 3 marbles. Jane has 5 more marbles than Tom.")
assert r.refused
assert r.refusal_reason == "no_query"
def test_refuses_negative_quantity():
r = read_relational(
"Tom has 3 marbles. Jane has 5 fewer marbles than Tom. "
"How many marbles does Jane have?"
)
assert r.refused
assert r.refusal_reason == "negative_quantity"
def test_refuses_empty():
assert read_relational("").refused
assert read_relational(" ").refusal_reason == "empty_input"