Adds a typed legality check that catches a narrow class of incoherent
finite-predicate surfaces before they ship. Scope is deliberately
narrow:
- generate/articulation_legality.py:
- SlotKind enum {VERB, NON_VERB, UNKNOWN}
- ArticulationLegality enum {LEGAL, ILLEGAL_NON_VERB_FINITE_PREDICATE}
- classify_predicate_slot_kind() — token allowlists for known verbs
and known non-verb nouns
- validate_finite_predicate_legality() — fails on negated +
NON_VERB; fail-open on UNKNOWN to preserve canary behavior
- generate/templates.py:
- _inflect_predicate: copular-aware negation
("is X" -> "is not X" instead of the default "does not be X")
- render_step: invokes the legality validator; returns
"I cannot realize that proposition coherently yet." when an
illegal shape is detected
The check is upstream of register / anchor-lens transforms (presentation
+ substantive axes both downstream of the realizer); no interaction
with R6 / ADR-0073 layering.
Tests pin:
- NON_VERB + negated -> ILLEGAL_NON_VERB_FINITE_PREDICATE
- UNKNOWN + negated -> LEGAL (fail-open preserved)
- render_step returns the disclosure string when illegal detected
- render_step still produces the fall-through surface on UNKNOWN
Validation:
- Cognition eval byte-identical (100/100/91.7/100)
- 370 realizer / lens / register / pack / lane tests pass
- anchor-lens-tour + register-tour both green
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from generate.articulation_legality import (
|
|
ArticulationLegality,
|
|
SlotKind,
|
|
validate_finite_predicate_legality,
|
|
)
|
|
from generate.graph_planner import RhetoricalMove
|
|
from generate.templates import render_step
|
|
|
|
|
|
def test_c15_rejects_known_nonverb_finite_predicate_under_negation() -> None:
|
|
verdict = validate_finite_predicate_legality(
|
|
predicate_humanized="thought",
|
|
negated=True,
|
|
)
|
|
assert verdict.legality is ArticulationLegality.ILLEGAL_NON_VERB_FINITE_PREDICATE
|
|
assert verdict.predicate_kind is SlotKind.NON_VERB
|
|
|
|
|
|
def test_c15_fail_open_on_unknown_predicate_kind() -> None:
|
|
verdict = validate_finite_predicate_legality(
|
|
predicate_humanized="quuxified",
|
|
negated=True,
|
|
)
|
|
assert verdict.legality is ArticulationLegality.LEGAL
|
|
assert verdict.predicate_kind is SlotKind.UNKNOWN
|
|
|
|
|
|
def test_render_step_discloses_when_illegal_shape_detected() -> None:
|
|
surface = render_step(
|
|
RhetoricalMove.ASSERT,
|
|
"right",
|
|
"thought",
|
|
"truth",
|
|
negated=True,
|
|
)
|
|
assert surface == "I cannot realize that proposition coherently yet."
|
|
|
|
|
|
def test_render_step_keeps_unknown_predicate_fail_open() -> None:
|
|
surface = render_step(
|
|
RhetoricalMove.ASSERT,
|
|
"signal",
|
|
"quuxified",
|
|
"truth",
|
|
negated=True,
|
|
)
|
|
assert surface == "signal does not quuxified truth"
|
|
|