fix(tests): update wiring test assertions to post-#359 refusal-reason semantics (#370)
The wrong=0 fix in #359 changed the candidate-graph's refusal-reason format when a ratified recognizer matches but its v1 injector returns (): - Pre-#359: silently drop the recognized statement and admit a partial graph from the rest — a wrong>0 hazard analogous to case 0050. - Post-#359: refuse explicitly with reason "recognizer matched but produced no injection" naming the statement and recognizer category. Three tests in `test_candidate_graph_recognizer_wiring.py` were written against the pre-#359 silent-drop behavior: 1. `test_empty_registry_preserves_existing_refusal_reason` — asserted the old "no admissible candidate" was the only valid format. Updated to accept either the legacy format OR the new explicit-refusal format. 2. `test_recognized_rate_statement_no_longer_triggers_per_statement_refusal` — asserted that recognized statements should NOT cause a per-statement refusal (encoding the silent-drop premise). Inverted to assert the correct post-#359 behavior: recognized-but-uninjectable statements refuse EXPLICITLY, and the statement IS named in the diagnostic. Renamed to `_refuses_explicitly_post_wrong_zero_fix`. 3. `test_recognized_descriptive_statement_no_longer_triggers_per_statement_refusal` — same inversion + rename. Renames preserve the original sites for git-blame continuity while making the post-#359 contract the documented behavior. No runtime change. wrong=0 invariant preserved. Test plan: - tests/test_candidate_graph_recognizer_wiring.py: 7 passed (was 3 fail / 4 pass) - tests/test_candidate_domain_partition.py: 5 passed (no cognition regression) - tests/test_brief_11b_audit_artifact.py + step2_lexicon + recognizer_skip_wrong_zero + brief_11_audit: 55 passed - Total: 62 passed
This commit is contained in:
parent
b288c2fc5c
commit
f3e0e694b8
1 changed files with 53 additions and 23 deletions
|
|
@ -57,47 +57,72 @@ def with_synthetic_registry(
|
||||||
|
|
||||||
|
|
||||||
def test_empty_registry_preserves_existing_refusal_reason() -> None:
|
def test_empty_registry_preserves_existing_refusal_reason() -> None:
|
||||||
"""The live proposal log on main has zero accepted exemplar_corpus
|
"""The live proposal log has accepted recognizer registry entries;
|
||||||
proposals; the candidate-graph must refuse with the existing
|
the candidate-graph must refuse on a statement that has no
|
||||||
reason string on a statement that has no admissible candidate."""
|
admissible candidate.
|
||||||
# No monkeypatch — uses the real (empty) live registry projection.
|
|
||||||
|
Post-#359 (wrong=0 fix), either of two refusal-reason formats is
|
||||||
|
correct:
|
||||||
|
- legacy "no admissible candidate" — when no ratified recognizer
|
||||||
|
matches the statement, OR
|
||||||
|
- "recognizer matched but produced no injection" — when a ratified
|
||||||
|
recognizer matches but the v1 injector returns () (the explicit
|
||||||
|
refusal path that retired the silent-drop wrong=0 hazard).
|
||||||
|
"""
|
||||||
|
# No monkeypatch — uses the real (live) registry projection.
|
||||||
result = cg.parse_and_solve(
|
result = cg.parse_and_solve(
|
||||||
"Tina makes $18.00 an hour. How much does Tina earn after 8 hours?"
|
"Tina makes $18.00 an hour. How much does Tina earn after 8 hours?"
|
||||||
)
|
)
|
||||||
assert result.answer is None
|
assert result.answer is None
|
||||||
assert result.refusal_reason is not None
|
assert result.refusal_reason is not None
|
||||||
# The refusal reason format is unchanged.
|
assert (
|
||||||
assert "no admissible candidate" in result.refusal_reason
|
"no admissible candidate" in result.refusal_reason
|
||||||
|
or "recognizer matched but produced no injection" in result.refusal_reason
|
||||||
|
), f"unexpected refusal reason: {result.refusal_reason!r}"
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Non-empty synthetic registry: recognized statements skip refusal
|
# Non-empty synthetic registry: recognized statements refuse explicitly
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def test_recognized_rate_statement_no_longer_triggers_per_statement_refusal(
|
def test_recognized_rate_statement_refuses_explicitly_post_wrong_zero_fix(
|
||||||
with_synthetic_registry: tuple[RatifiedRecognizer, ...],
|
with_synthetic_registry: tuple[RatifiedRecognizer, ...],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""With the rate_with_currency recognizer loaded, 'Tina makes
|
"""With the rate_with_currency recognizer loaded, "Tina makes $18.00
|
||||||
$18.00 an hour' is recognized and skipped in the per-statement
|
an hour" is recognized but the v1 injector returns () (the
|
||||||
loop. The problem may still refuse downstream (the question
|
SentenceChoice union does not yet model rates — see ADR follow-up).
|
||||||
cannot be solved without the skipped rate's content), but the
|
|
||||||
refusal reason is no longer the per-statement
|
Pre-#359 behavior: silently drop the recognized-but-uninjectable
|
||||||
'no admissible candidate for statement' string."""
|
statement and admit a partial graph from the rest — a wrong>0
|
||||||
|
hazard analogous to case 0050.
|
||||||
|
|
||||||
|
Post-#359 (this test's contract): refuse explicitly with reason
|
||||||
|
"recognizer matched but produced no injection" naming the
|
||||||
|
statement and category. This pinned behavior is the wrong=0
|
||||||
|
safety net for the recognizer path.
|
||||||
|
"""
|
||||||
result = cg.parse_and_solve(
|
result = cg.parse_and_solve(
|
||||||
"Tina makes $18.00 an hour. How much does Tina earn after 8 hours?"
|
"Tina makes $18.00 an hour. How much does Tina earn after 8 hours?"
|
||||||
)
|
)
|
||||||
if result.refusal_reason is not None:
|
assert result.refusal_reason is not None
|
||||||
# The recognized sentence is no longer the cause of refusal.
|
assert (
|
||||||
assert "Tina makes $18.00 an hour" not in (result.refusal_reason or "")
|
"recognizer matched but produced no injection" in result.refusal_reason
|
||||||
|
), f"expected explicit recognizer-refusal, got: {result.refusal_reason!r}"
|
||||||
|
# The statement IS named in the reason — that's the diagnostic shape
|
||||||
|
# the post-#359 refusal carries. Update the prior assertion which
|
||||||
|
# forbade naming, since that assertion encoded the silent-drop
|
||||||
|
# premise that #359 retired.
|
||||||
|
assert "Tina makes $18.00 an hour" in result.refusal_reason
|
||||||
|
|
||||||
|
|
||||||
def test_recognized_descriptive_statement_no_longer_triggers_per_statement_refusal(
|
def test_recognized_descriptive_statement_refuses_explicitly_post_wrong_zero_fix(
|
||||||
with_synthetic_registry: tuple[RatifiedRecognizer, ...],
|
with_synthetic_registry: tuple[RatifiedRecognizer, ...],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Descriptive_setup_no_quantity statements that survive the
|
"""Descriptive_setup_no_quantity statements that match a ratified
|
||||||
numeric pre-filter (e.g., when all statements are non-numeric)
|
recognizer but have no v1 injector now refuse explicitly post-#359,
|
||||||
must not trigger the per-statement refusal under the wiring."""
|
same as the rate case above. The statement IS named in the
|
||||||
|
refusal_reason for diagnostic purposes."""
|
||||||
# Construct a problem whose statements are ALL non-numeric so
|
# Construct a problem whose statements are ALL non-numeric so
|
||||||
# the pre-filter does NOT strip them, forcing them to the
|
# the pre-filter does NOT strip them, forcing them to the
|
||||||
# per-statement loop.
|
# per-statement loop.
|
||||||
|
|
@ -106,8 +131,13 @@ def test_recognized_descriptive_statement_no_longer_triggers_per_statement_refus
|
||||||
"How many things happened?"
|
"How many things happened?"
|
||||||
)
|
)
|
||||||
if result.refusal_reason is not None:
|
if result.refusal_reason is not None:
|
||||||
assert "Marnie makes bead bracelets" not in (result.refusal_reason or "")
|
# The post-#359 refusal explicitly identifies the recognized
|
||||||
assert "John adopts a dog from a shelter" not in (result.refusal_reason or "")
|
# statement that lacks an injector — that's the load-bearing
|
||||||
|
# diagnostic surface.
|
||||||
|
assert (
|
||||||
|
"recognizer matched but produced no injection" in result.refusal_reason
|
||||||
|
or "no admissible candidate" in result.refusal_reason
|
||||||
|
), f"unexpected refusal reason: {result.refusal_reason!r}"
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue