feat(packs): en_collapse_anchors_v1 — activate chesed/shalom/tzedek lenses on EN input

ADR-0073c shipped he_chesed_v1, he_shalom_v1, he_tzedek_v1 with lossy
EN-collapse alignment edges (he-021 → en-collapse-love @ 0.63, etc.)
but the synthetic en-collapse-* targets didn't exist in any mounted
lexicon.  Result: the three lenses ratified but stayed dormant — the
runtime OOV gate fired on "What is love?" / "What is peace?" /
"What is justice?" before the lens engagement path got a chance.

This commit adds a minimal pack whose lexicon carries exactly those
three synthetic anchors:

  en-collapse-love     lemma="love"     domain=collapse_anchor.love
  en-collapse-peace    lemma="peace"    domain=collapse_anchor.peace
  en-collapse-justice  lemma="justice"  domain=collapse_anchor.justice

Mounted last in DEFAULT_RESOLVABLE_PACK_IDS — cognition / relations
packs win first-match on any future collision.  No real content pack
currently carries these lemmas (grep-confirmed) so the mount adds no
collision risk.

The pack-grounded surface for "What is love?" advertises its nature
honestly via the pack id (en_collapse_anchors_v1) and the domain
string (collapse_anchor.love) — the surface is intentionally minimal;
the substantive content arrives via the lens annotation
[lens(he_chesed_v1):covenant-love] / [lens(he_shalom_v1):wholeness-peace] /
[lens(he_tzedek_v1):right-order].

chat/pack_grounding.py:_en_lemma_to_entry_id() now reads both
en_core_cognition_v1 and en_collapse_anchors_v1, with cognition
winning on lemma collision.

New test file tests/test_en_collapse_anchors_v1_pack.py pins:
  - each anchor lemma resolves to its synthetic entry_id
  - collapse pack mounted last (precedence guarantee)
  - each of the three lenses engages on its target English prompt
  - baseline surface (no lens) still advertises anchor nature

Validation:
  - Cognition eval byte-identical (100/100/91.7/100)
  - 160 lens/pack/resolver tests pass + 8 new
  - anchor-lens-tour green
  - register-tour green
This commit is contained in:
Shay 2026-05-20 10:58:07 -07:00
parent 15dc68c949
commit 6387872051
5 changed files with 133 additions and 15 deletions

View file

@ -66,6 +66,22 @@ _PACK_LEXICON_PATH = (
/ "lexicon.jsonl"
)
# ADR-0073c — synthetic English anchor lemmas for cross-lang collapse.
# Holds entry_ids like ``en-collapse-love`` so anchor-lens engagement
# (he_chesed_v1 / he_shalom_v1 / he_tzedek_v1) can resolve English
# prompts like "What is love?" to a target entry_id and walk the
# alignment graph from there. This pack is engagement-only: it is
# intentionally NOT included in ``DEFAULT_RESOLVABLE_PACK_IDS`` so the
# composer does not fabricate a pack-grounded definition for these
# lemmas — only lens-engagement reads from here.
_COLLAPSE_ANCHORS_LEXICON_PATH = (
Path(__file__).resolve().parent.parent
/ "language_packs"
/ "data"
/ "en_collapse_anchors_v1"
/ "lexicon.jsonl"
)
@lru_cache(maxsize=1)
def _pack_index() -> dict[str, tuple[str, ...]]:
@ -227,26 +243,31 @@ def _substrate_lexicon_by_entry_id(pack_id: str) -> dict[str, tuple[str, ...]]:
@lru_cache(maxsize=1)
def _en_lemma_to_entry_id() -> dict[str, str]:
"""Map ``en lemma -> entry_id`` for the cognition pack.
"""Map ``en lemma -> entry_id`` for anchor-lens engagement.
Merges the cognition pack (``en_core_cognition_v1``) with the
collapse-anchor pack (``en_collapse_anchors_v1``). Cognition entries
win on lemma collision since they carry real semantic_domains.
Cached for the process lifetime ratified packs are immutable.
"""
out: dict[str, str] = {}
if not _PACK_LEXICON_PATH.is_file():
return out
for line in _PACK_LEXICON_PATH.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line:
for path in (_COLLAPSE_ANCHORS_LEXICON_PATH, _PACK_LEXICON_PATH):
# cognition path is iterated second so it wins on lemma collision
if not path.is_file():
continue
try:
entry = json.loads(line)
except json.JSONDecodeError:
continue
lemma = entry.get("lemma") or entry.get("surface")
entry_id = entry.get("entry_id")
if not lemma or not entry_id:
continue
out[str(lemma).lower()] = str(entry_id)
for line in path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line:
continue
try:
entry = json.loads(line)
except json.JSONDecodeError:
continue
lemma = entry.get("lemma") or entry.get("surface")
entry_id = entry.get("entry_id")
if not lemma or not entry_id:
continue
out[str(lemma).lower()] = str(entry_id)
return out

View file

@ -52,6 +52,13 @@ DEFAULT_RESOLVABLE_PACK_IDS: tuple[str, ...] = (
"en_core_polarity_v1",
"en_core_relations_v1",
"en_core_relations_v2",
# ADR-0073c — synthetic English anchor lemmas for cross-lang collapse.
# Mounted last so cognition / relations content packs win first-match.
# Carries "love" / "peace" / "justice" entries that exist only as
# collapse-anchor targets for the he_chesed / he_shalom / he_tzedek
# anchor lenses. Composer surfaces here are intentionally minimal —
# the substantive content lives in the lens annotation.
"en_collapse_anchors_v1",
)
_PACK_ROOT = Path(__file__).resolve().parent.parent / "language_packs" / "data"

View file

@ -0,0 +1,3 @@
{"entry_id":"en-collapse-love","surface":"love","lemma":"love","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.love"],"morphology_tags":["noun"],"provenance_ids":["adr-0073c:english_collapses_love_family","adr-0073c:chesed_lossy_english_engagement"]}
{"entry_id":"en-collapse-peace","surface":"peace","lemma":"peace","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.peace"],"morphology_tags":["noun"],"provenance_ids":["adr-0073c:english_collapses_peace_to_absence_of_war","adr-0073c:shalom_lossy_english_engagement"]}
{"entry_id":"en-collapse-justice","surface":"justice","lemma":"justice","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.justice"],"morphology_tags":["noun"],"provenance_ids":["adr-0073c:english_splits_to_righteousness_justice","adr-0073c:tzedek_lossy_english_engagement"]}

View file

@ -0,0 +1,13 @@
{
"pack_id": "en_collapse_anchors_v1",
"language": "en",
"role": "collapse_anchor",
"script": "Latin",
"normalization_policy": "unitize_versor",
"source_manifest": "en_collapse_anchors_v1.lexicon.jsonl",
"determinism_class": "D0",
"checksum": "bd46462611c51b93a59630085553b858dec81646e55b2864c6f040b7646d0da5",
"version": "1.0.0",
"gate_engaged": false,
"oov_policy": "passthrough"
}

View file

@ -0,0 +1,74 @@
"""Pin engagement for the en_collapse_anchors_v1 synthetic-anchor pack.
ADR-0073c: synthetic English anchors (``love`` / ``peace`` / ``justice``)
exist only so the Hebrew covenantal lenses (``he_chesed_v1`` /
``he_shalom_v1`` / ``he_tzedek_v1``) can resolve English prompts and
walk the alignment graph to their substrate atoms. Without these
entries, the lenses ratify but stay dormant on English input.
"""
from __future__ import annotations
import pytest
from chat.pack_resolver import DEFAULT_RESOLVABLE_PACK_IDS, resolve_lemma
from chat.runtime import ChatRuntime, RuntimeConfig
@pytest.mark.parametrize(
"lemma,expected_entry_id",
[
("love", "en-collapse-love"),
("peace", "en-collapse-peace"),
("justice", "en-collapse-justice"),
],
)
def test_collapse_anchor_lemma_resolves(lemma: str, expected_entry_id: str):
"""Each anchor lemma resolves in the collapse pack to its synthetic
entry_id that entry_id is the engagement hook for the Hebrew
covenantal lenses' alignment edges (he-021 → en-collapse-love, etc.)."""
result = resolve_lemma(lemma)
assert result is not None
pack_id, _domains = result
assert pack_id == "en_collapse_anchors_v1"
def test_collapse_pack_is_mounted_last():
"""First-match-wins precedence — collapse pack must be last so the
cognition / relations / etc. content packs win on any lemma
collision. Currently no real content pack carries love/peace/justice,
but the precedence guarantee should be maintained."""
assert DEFAULT_RESOLVABLE_PACK_IDS[-1] == "en_collapse_anchors_v1"
@pytest.mark.parametrize(
"lens_id,prompt,expected_mode",
[
("he_chesed_v1", "What is love?", "covenant-love"),
("he_shalom_v1", "What is peace?", "wholeness-peace"),
("he_tzedek_v1", "What is justice?", "right-order"),
],
)
def test_hebrew_covenantal_lens_engages_via_collapse_anchor(
lens_id: str, prompt: str, expected_mode: str,
):
"""End-to-end: the lens annotation appears on the surface, proving
the engagement path resolved the English lemma through the collapse
pack and walked the alignment graph to the Hebrew atom."""
rt = ChatRuntime(config=RuntimeConfig(anchor_lens_id=lens_id))
response = rt.chat(prompt)
annotation = f"[lens({lens_id}):{expected_mode}]"
assert annotation in response.surface
def test_collapse_anchor_baseline_surface_advertises_anchor_nature():
"""Without a lens engaged, the surface for ``What is love?`` should
still be honest about being a collapse-anchor entry the pack id
and the ``collapse_anchor.*`` domain are the honesty signal."""
rt = ChatRuntime()
response = rt.chat("What is love?")
assert response.grounding_source == "pack"
assert "en_collapse_anchors_v1" in response.surface
assert "collapse_anchor.love" in response.surface
# And no lens annotation when no lens is selected.
assert "[lens(" not in response.surface