Tests on main had drifted from intentional substrate changes that
weren't propagated to their fixtures or pinned values. Categories:
1. PackMutationProposal missing source= arg (3 tests across
test_mutation_proposal_type, test_provenance, test_expert_demo_runnable):
add ProposalSource(kind="operator", source_id="", emitted_at_revision="test")
to the shared fixture. test_expert_demo_runnable also retargets the
"unpromoted domain" example from systems_software (now promoted) to
arithmetic (real but unpromoted).
2. Pack content grew (test_en_core_meta_v1_pack 73→77 entries, 49→53 verbs;
test_en_core_spatial_v1_pack 24→25 entries adding "places" plural surface):
bump expected counts; allow new provenance shapes from the
adr-0085-style-v2 review (including the seed:core_meta/seed:core_spatial
author-time typos on two entries each — documented inline rather than
masked).
3. Registry self-documenting "add names to the set" failures
(test_lane_sha_verifier: add curriculum_loop_closure;
test_register_runtime_threading: add gloss_aware_cause_surface,
pack_grounded_unknown_surface, teaching_grounded_surface_transitive).
4. Gloss content was seeded where tests pinned None
(test_pack_resolver_glosses TestMissingGlossesIsBackCompat): switch
the no-glosses pack from en_core_relations_v1 (since glossed) to
en_minimal_v1 (still gloss-free); narrow resolve_gloss probe to that
pack so other packs' glosses can't shadow.
5. Entry-id renumber from cognition-pack expansion
(test_language_pack_cache): en-core-cog-085 → en-core-cog-091.
6. Holdout tests fail without CORE_HOLDOUT_KEY or local plaintext
(test_eval_holdout_split + test_transitive_surface): add
_requires_holdout skip-marker mirroring _decrypt_holdout's contract;
gate the transitive_surface holdout iteration on the same check.
7. Byte-identity surface guards regressed after the gloss-aware
composer landed (test_realizer_guard_holdout, test_prompt_diversity_runner,
test_register_substantive_consumption): re-pin to current surfaces
("Light is a visible medium that reveals truth." replaces "Light is a
source of revelation that makes things knowable.", etc.). The guard's
regression-catching role is preserved by pinning current output going
forward; the new gloss-driven phrasings are visibly more grounded.
Touched 14 test files: 176 passed, 4 skipped (holdout-gated), 0 failed
on a targeted re-run. No production code touched.
437 lines
14 KiB
Python
437 lines
14 KiB
Python
"""ADR-0077 (R6) — per-knob unit + end-to-end coverage of
|
|
``chat/register_substantive.py``.
|
|
|
|
Two test families:
|
|
|
|
* Pure-unit tests against synthetic canonical surfaces — assert each
|
|
knob is the deterministic string transform documented in the ADR,
|
|
with no dependency on the runtime.
|
|
* End-to-end tests run a real ChatRuntime under each ratified
|
|
register and assert the user-facing surface matches the post-
|
|
substantive expectation.
|
|
|
|
C1 (ADR-0075) preservation: every R6 knob combination must produce a
|
|
surface that the realizer guard accepts. This module pins that
|
|
contract by running the guard against every produced surface.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Mapping
|
|
|
|
import pytest
|
|
|
|
from chat.register_substantive import apply_substantive_register
|
|
from chat.runtime import ChatRuntime
|
|
from core.cognition.pipeline import CognitiveTurnPipeline
|
|
from core.config import RuntimeConfig
|
|
from generate.realizer_guard import check_surface
|
|
from packs.register.loader import RegisterPack, load_register_pack
|
|
|
|
|
|
# ---------- Fake register for synthetic unit coverage ----------
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class _FakeMarkers:
|
|
openings: tuple[str, ...] = ()
|
|
transitions: tuple[str, ...] = ()
|
|
closings: tuple[str, ...] = ()
|
|
|
|
def is_empty(self) -> bool:
|
|
return True
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class _FakeRegister:
|
|
"""Minimal duck-type that ``apply_substantive_register`` accepts.
|
|
|
|
Only ``realizer_overrides`` is read in the substantive path.
|
|
"""
|
|
|
|
realizer_overrides: Mapping[str, object] = field(default_factory=dict)
|
|
discourse_markers: _FakeMarkers = field(default_factory=_FakeMarkers)
|
|
|
|
|
|
def _r(overrides: Mapping[str, object]) -> _FakeRegister:
|
|
return _FakeRegister(realizer_overrides=dict(overrides))
|
|
|
|
|
|
_DEF_CANONICAL = (
|
|
"Light is a visible medium that reveals truth. "
|
|
"pack-grounded (en_core_cognition_v1)."
|
|
)
|
|
_DEF_CANONICAL_LENS = (
|
|
"Light is a visible medium that reveals truth. "
|
|
"pack-grounded (en_core_cognition_v1) [lens(grc_logos_v1):systematic]."
|
|
)
|
|
_CMP_CANONICAL = (
|
|
"light (cognition.illumination; logos.core) contrasts with "
|
|
"truth (cognition.truth; logos.core) — pack-grounded "
|
|
"(en_core_cognition_v1). No session evidence yet."
|
|
)
|
|
_DOT_CANONICAL = (
|
|
"light — pack-grounded (en_core_cognition_v1): "
|
|
"cognition.illumination; logos.core; cognition.knowledge. "
|
|
"No session evidence yet."
|
|
)
|
|
|
|
|
|
# ---------- No-op contract ----------
|
|
|
|
|
|
def test_empty_overrides_is_byte_identical():
|
|
"""The default register (empty overrides) must be a no-op."""
|
|
out = apply_substantive_register(_DEF_CANONICAL, _r({}))
|
|
assert out == _DEF_CANONICAL
|
|
|
|
|
|
def test_all_knobs_false_is_byte_identical():
|
|
"""Explicit False values must also be a no-op — the ``.get(key)``
|
|
lookup returns ``False`` which is falsy."""
|
|
out = apply_substantive_register(
|
|
_DEF_CANONICAL,
|
|
_r({
|
|
"drop_provenance_tag": False,
|
|
"compress_gloss": False,
|
|
"drop_articles": False,
|
|
"append_semantic_domain_clause": False,
|
|
}),
|
|
)
|
|
assert out == _DEF_CANONICAL
|
|
|
|
|
|
def test_empty_canonical_is_byte_identical():
|
|
out = apply_substantive_register("", _r({"drop_provenance_tag": True}))
|
|
assert out == ""
|
|
|
|
|
|
# ---------- drop_provenance_tag ----------
|
|
|
|
|
|
def test_drop_provenance_strips_trailing_gloss_clause():
|
|
out = apply_substantive_register(
|
|
_DEF_CANONICAL, _r({"drop_provenance_tag": True}),
|
|
)
|
|
assert "pack-grounded" not in out
|
|
assert out.endswith("reveals truth.")
|
|
assert "..," not in out and ".." not in out # no double-period bug
|
|
|
|
|
|
def test_drop_provenance_preserves_lens_annotation():
|
|
out = apply_substantive_register(
|
|
_DEF_CANONICAL_LENS, _r({"drop_provenance_tag": True}),
|
|
)
|
|
assert "pack-grounded" not in out
|
|
assert "[lens(grc_logos_v1):systematic]" in out
|
|
|
|
|
|
def test_drop_provenance_strips_infix_em_dash_form():
|
|
out = apply_substantive_register(
|
|
_CMP_CANONICAL, _r({"drop_provenance_tag": True}),
|
|
)
|
|
assert "pack-grounded" not in out
|
|
# Em-dash before the provenance is consumed by the infix regex.
|
|
assert " — pack-grounded" not in out
|
|
assert "contrasts with truth" in out
|
|
assert "No session evidence yet" in out
|
|
|
|
|
|
def test_drop_provenance_strips_dotted_disclosure_form():
|
|
out = apply_substantive_register(
|
|
_DOT_CANONICAL, _r({"drop_provenance_tag": True}),
|
|
)
|
|
assert "pack-grounded" not in out
|
|
assert out.startswith("light:") # em-dash + provenance gone; colon kept
|
|
|
|
|
|
# ---------- compress_gloss ----------
|
|
|
|
|
|
def test_compress_gloss_replaces_is_a():
|
|
out = apply_substantive_register(
|
|
"Light is a source of revelation.", _r({"compress_gloss": True}),
|
|
)
|
|
assert out == "Light: source of revelation."
|
|
|
|
|
|
def test_compress_gloss_replaces_is_an():
|
|
out = apply_substantive_register(
|
|
"Answer is an example of speech.", _r({"compress_gloss": True}),
|
|
)
|
|
assert out == "Answer: example of speech."
|
|
|
|
|
|
def test_compress_gloss_replaces_is_the():
|
|
out = apply_substantive_register(
|
|
"Beginning is the origin point.", _r({"compress_gloss": True}),
|
|
)
|
|
assert out == "Beginning: origin point."
|
|
|
|
|
|
def test_compress_gloss_replaces_bare_is():
|
|
out = apply_substantive_register(
|
|
"Cause is that which produces effect.",
|
|
_r({"compress_gloss": True}),
|
|
)
|
|
assert out == "Cause: that which produces effect."
|
|
|
|
|
|
def test_compress_gloss_only_first_occurrence():
|
|
"""Multiple ``is`` tokens must not all collapse — only the gloss
|
|
opener. Mangling a subordinate clause's ``is`` would be a bug."""
|
|
out = apply_substantive_register(
|
|
"X is a Y. The reason is clear.", _r({"compress_gloss": True}),
|
|
)
|
|
assert out == "X: Y. The reason is clear."
|
|
|
|
|
|
def test_compress_gloss_noop_on_comparison():
|
|
"""COMPARISON form has no ``is`` — must be byte-identical."""
|
|
out = apply_substantive_register(
|
|
_CMP_CANONICAL, _r({"compress_gloss": True}),
|
|
)
|
|
assert out == _CMP_CANONICAL
|
|
|
|
|
|
# ---------- drop_articles ----------
|
|
|
|
|
|
def test_drop_articles_strips_mid_sentence_a():
|
|
out = apply_substantive_register(
|
|
"Light reveals a truth in this case.", _r({"drop_articles": True}),
|
|
)
|
|
assert out == "Light reveals truth in this case."
|
|
|
|
|
|
def test_drop_articles_strips_mid_sentence_the():
|
|
out = apply_substantive_register(
|
|
"Light reveals the truth.", _r({"drop_articles": True}),
|
|
)
|
|
assert out == "Light reveals truth."
|
|
|
|
|
|
def test_drop_articles_preserves_article_after_not():
|
|
"""C1 R3 safety: must not collapse ``is not a claim`` to ``is not
|
|
claim`` because R3 fires when a be-negation is followed by a VERB.
|
|
``claim`` is a NOUN so R3 wouldn't fire anyway, but the lookbehind
|
|
guards us against a more dangerous case in the future."""
|
|
out = apply_substantive_register(
|
|
"Light is not a claim.", _r({"drop_articles": True}),
|
|
)
|
|
assert out == "Light is not a claim."
|
|
|
|
|
|
def test_drop_articles_collapses_double_space_artifact():
|
|
"""Adjacent removals must not leave a double space in the output."""
|
|
out = apply_substantive_register(
|
|
"Walks the path of a sage.", _r({"drop_articles": True}),
|
|
)
|
|
assert " " not in out
|
|
assert out == "Walks path of sage."
|
|
|
|
|
|
# ---------- append_semantic_domain_clause ----------
|
|
|
|
|
|
def test_append_picks_lex_first_unused_atom():
|
|
out = apply_substantive_register(
|
|
"Light is the source.",
|
|
_r({"append_semantic_domain_clause": True}),
|
|
semantic_domains=("logos.core", "cognition.illumination"),
|
|
)
|
|
# Sorted atoms: ("cognition.illumination", "logos.core").
|
|
# Both are absent from canonical, so the first lex-sorted wins.
|
|
assert out.endswith(" Related: cognition.illumination.")
|
|
|
|
|
|
def test_append_skips_atom_already_in_canonical():
|
|
out = apply_substantive_register(
|
|
"Light is a source in cognition.illumination.",
|
|
_r({"append_semantic_domain_clause": True}),
|
|
semantic_domains=("cognition.illumination", "logos.core"),
|
|
)
|
|
assert out.endswith(" Related: logos.core.")
|
|
|
|
|
|
def test_append_noop_when_all_atoms_already_used():
|
|
canonical = "Light: covers logos.core cognition.illumination."
|
|
out = apply_substantive_register(
|
|
canonical,
|
|
_r({"append_semantic_domain_clause": True}),
|
|
semantic_domains=("cognition.illumination", "logos.core"),
|
|
)
|
|
assert out == canonical
|
|
|
|
|
|
def test_append_noop_when_no_atoms_supplied():
|
|
out = apply_substantive_register(
|
|
_DEF_CANONICAL,
|
|
_r({"append_semantic_domain_clause": True}),
|
|
semantic_domains=(),
|
|
)
|
|
assert out == _DEF_CANONICAL
|
|
|
|
|
|
# ---------- Knob composition (terse_v1 combined) ----------
|
|
|
|
|
|
def test_terse_full_combo_def_form():
|
|
"""compress_gloss + drop_provenance_tag + drop_articles together
|
|
on the canonical DEFINITION form."""
|
|
out = apply_substantive_register(
|
|
_DEF_CANONICAL,
|
|
_r({
|
|
"compress_gloss": True,
|
|
"drop_provenance_tag": True,
|
|
"drop_articles": True,
|
|
}),
|
|
)
|
|
# compress: "Light is a visible medium ... truth." -> "Light: visible medium ... truth."
|
|
# drop_articles: removes leftover "a/the" articles.
|
|
# drop_provenance_tag: trailing pack-grounded clause removed.
|
|
assert out == "Light: visible medium that reveals truth."
|
|
|
|
|
|
def test_terse_full_combo_with_lens():
|
|
"""Lens annotation must survive the terse combo."""
|
|
out = apply_substantive_register(
|
|
_DEF_CANONICAL_LENS,
|
|
_r({
|
|
"compress_gloss": True,
|
|
"drop_provenance_tag": True,
|
|
"drop_articles": True,
|
|
}),
|
|
)
|
|
assert "[lens(grc_logos_v1):systematic]" in out
|
|
assert "pack-grounded" not in out
|
|
|
|
|
|
# ---------- Guard safety (C1 preservation) ----------
|
|
|
|
|
|
def _trivial_pos_lookup(_token: str) -> None:
|
|
"""Pack-less POS lookup — returns None for every token. The C1
|
|
guard then fails-open on every unknown token, which is what we
|
|
want for synthetic unit assertions.
|
|
"""
|
|
return None
|
|
|
|
|
|
@pytest.mark.parametrize("knobs", [
|
|
{"compress_gloss": True},
|
|
{"drop_provenance_tag": True},
|
|
{"drop_articles": True},
|
|
{"append_semantic_domain_clause": True},
|
|
{
|
|
"compress_gloss": True,
|
|
"drop_provenance_tag": True,
|
|
"drop_articles": True,
|
|
},
|
|
])
|
|
def test_every_knob_combination_passes_guard(knobs):
|
|
"""invariant_realizer_no_illegal_articulation preservation —
|
|
no R6 knob combination produces a surface that trips R2/R3."""
|
|
domains = ("cognition.illumination", "logos.core")
|
|
for canonical in (_DEF_CANONICAL, _DEF_CANONICAL_LENS, _CMP_CANONICAL, _DOT_CANONICAL):
|
|
out = apply_substantive_register(
|
|
canonical, _r(knobs), semantic_domains=domains,
|
|
)
|
|
v = check_surface(out, pos_lookup=_trivial_pos_lookup)
|
|
assert v.status == "ok", (
|
|
f"knobs={knobs} produced guard-rejected surface "
|
|
f"{out!r} from canonical {canonical!r}: {v}"
|
|
)
|
|
|
|
|
|
# ---------- End-to-end against real packs + runtime ----------
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def neutral_def_surface() -> str:
|
|
rt = ChatRuntime(config=RuntimeConfig(register_pack_id="default_neutral_v1"))
|
|
pipe = CognitiveTurnPipeline(runtime=rt)
|
|
pipe.run("What is light?")
|
|
return rt.turn_log[-1].surface
|
|
|
|
|
|
def test_e2e_terse_drops_provenance_tag():
|
|
rt = ChatRuntime(config=RuntimeConfig(register_pack_id="terse_v1"))
|
|
pipe = CognitiveTurnPipeline(runtime=rt)
|
|
pipe.run("What is light?")
|
|
te = rt.turn_log[-1]
|
|
assert "pack-grounded" not in te.surface
|
|
assert te.register_canonical_surface != ""
|
|
assert "pack-grounded" in te.register_canonical_surface
|
|
|
|
|
|
def test_e2e_terse_compresses_gloss():
|
|
rt = ChatRuntime(config=RuntimeConfig(register_pack_id="terse_v1"))
|
|
pipe = CognitiveTurnPipeline(runtime=rt)
|
|
pipe.run("What is light?")
|
|
te = rt.turn_log[-1]
|
|
assert "Light: " in te.surface
|
|
# Gloss compression strips " is a "; raw " is a " must NOT survive
|
|
# in the user-facing surface under terse.
|
|
assert " is a " not in te.surface
|
|
|
|
|
|
def test_e2e_terse_drops_articles():
|
|
rt = ChatRuntime(config=RuntimeConfig(register_pack_id="terse_v1"))
|
|
pipe = CognitiveTurnPipeline(runtime=rt)
|
|
pipe.run("What is light?")
|
|
te = rt.turn_log[-1]
|
|
# Should not contain standalone mid-sentence articles in the
|
|
# compressed surface. ``" a "`` and ``" the "`` are mid-sentence
|
|
# markers we expect to be absent in the compressed gloss.
|
|
assert " a " not in te.surface
|
|
assert " the " not in te.surface
|
|
|
|
|
|
def test_e2e_convivial_appends_related_clause(neutral_def_surface: str):
|
|
rt = ChatRuntime(config=RuntimeConfig(register_pack_id="convivial_v1"))
|
|
pipe = CognitiveTurnPipeline(runtime=rt)
|
|
pipe.run("What is light?")
|
|
te = rt.turn_log[-1]
|
|
assert "Related: " in te.surface
|
|
# The Related clause must be derived from a pack atom — atoms in
|
|
# the cognition pack are dotted ``domain.subdomain`` form (e.g.
|
|
# ``cognition.illumination``, ``logos.core``). Match a dotted
|
|
# atom inside the Related clause specifically.
|
|
import re
|
|
m = re.search(r"Related: ([\w]+\.[\w.]+)\.", te.surface)
|
|
assert m is not None, f"no dotted atom in Related clause: {te.surface!r}"
|
|
assert "." in m.group(1)
|
|
|
|
|
|
def test_e2e_neutral_unchanged_by_r6(neutral_def_surface: str):
|
|
"""default_neutral_v1 has no R6 knobs → surface must be identical
|
|
to the pre-R6 byte-for-byte expected gloss."""
|
|
expected = (
|
|
"Light is a visible medium that reveals truth. "
|
|
"pack-grounded (en_core_cognition_v1)."
|
|
)
|
|
assert neutral_def_surface == expected
|
|
|
|
|
|
# ---------- Pack-loaded knob schema ----------
|
|
|
|
|
|
@pytest.mark.parametrize("register_id,expected_keys", [
|
|
("default_neutral_v1", set()),
|
|
(
|
|
"terse_v1",
|
|
{"compress_gloss", "disclosure_domain_count", "drop_articles",
|
|
"drop_provenance_tag"},
|
|
),
|
|
("convivial_v1", {"append_semantic_domain_clause"}),
|
|
])
|
|
def test_register_pack_carries_expected_r6_keys(
|
|
register_id: str, expected_keys: set[str],
|
|
):
|
|
"""Pin the on-disk pack contents so future re-ratification can't
|
|
silently drop the R6 knobs."""
|
|
pack = load_register_pack(register_id)
|
|
actual_keys = set(pack.realizer_overrides.keys())
|
|
assert actual_keys == expected_keys
|