core/tests/test_relational_symbolic_reader.py
Shay 5c77c9eece feat(field-wedge): ablation verdict — field is decoration on additive (C3) (Phase W.2)
The falsifiable experiment's measurements #2 (ablation) and #3 (diversity). Builds the
competent, code-disjoint SYMBOLIC reader (the control arm AND the C3 capability path)
and the ablation instrument that runs both readers through the real
verify_tier2_agreement gate.

VERDICT: C3 — the field is decoration on this domain (a sanctioned, honest negative):
- field_wrong_commits = []  (wrong=0 holds; the per-step drift guard refuses bad ints)
- field_caught_symbolic_errors = []  (the field caught ZERO symbolic errors)
- per-class diversity = 0 everywhere (both readers agree and are both correct)
- the only admitted-set change is the field LOSING coverage at the precision ceiling.

Insight: on forward-substitutable relations, geometric translation IS arithmetic
addition, so there is no metric over-determination for the field to exploit — field and
symbol are common-mode (Knight-Leveson), not a genuine second derivation. This is the
deductive finding's twin: logic was combinatorial (field can't earn it), additive is
arithmetically trivial (field adds nothing). The field needs metric-nontrivial AND
arithmetically-hard structure to earn a reasoning role — dedicated research, not
near-term. Field-as-reasoner is NOT earned; no field vote enters any serving path; the
field stays a servant. Capability path = symbolic (C3), not shipped here.

- generate/relational_symbolic_reader.py: competent independent reader (pure int).
- evals/relational_metric/ablation.py: the reusable decoration instrument.
- docs/analysis/field-wedge-ablation-result-2026-06-04.md: the recorded verdict.

All prior artifacts STAY (field reader = real wrong=0 read demo + 3rd panel domain).
Green: full wedge suite 104; 53 architectural invariants.
2026-06-04 19:44:22 -07:00

59 lines
2.1 KiB
Python

"""The symbolic reader — the ablation control arm and the C3 capability path.
It must be a *competent* reader (correct on the grammar, fences the same out-of-domain
cases, detects over-determination), so the ablation is a fair test of whether the field
adds anything over it. Unlike the field it has no precision limit (pure int).
"""
from __future__ import annotations
from generate.relational_symbolic_reader import READER_LINEAGE, read_relational
def test_commits_additive_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 and r.answer == 8
assert r.reader_lineage == READER_LINEAGE
def test_commits_part_whole_sum():
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 and r.answer == 11
def test_commits_beyond_field_ceiling():
"""The symbolic reader has no f64 precision limit — it commits where the field
refuses (over_ceiling). This is the field's coverage liability, not a symbolic bug."""
r = read_relational("Gus has 9000000 apples. How many apples does Gus have?")
assert not r.refused and r.answer == 9000000
def test_fences_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 and r.refusal_reason == "fenced_multiplicative"
def test_detects_over_determination():
"""A competent reader refuses a conflicting re-statement (so the field's geometric
coherence check is not a unique advantage)."""
r = read_relational(
"Tom has 3 marbles. Tom has 5 marbles. How many marbles does Tom have?"
)
assert r.refused and r.refusal_reason == "over_determined_conflict"
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 and r.refusal_reason == "non_forward_substitutable"