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:
parent
15dc68c949
commit
6387872051
5 changed files with 133 additions and 15 deletions
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
3
language_packs/data/en_collapse_anchors_v1/lexicon.jsonl
Normal file
3
language_packs/data/en_collapse_anchors_v1/lexicon.jsonl
Normal 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"]}
|
||||
13
language_packs/data/en_collapse_anchors_v1/manifest.json
Normal file
13
language_packs/data/en_collapse_anchors_v1/manifest.json
Normal 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"
|
||||
}
|
||||
74
tests/test_en_collapse_anchors_v1_pack.py
Normal file
74
tests/test_en_collapse_anchors_v1_pack.py
Normal 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
|
||||
Loading…
Reference in a new issue