diff --git a/language_packs/data/en_collapse_anchors_v1/lexicon.jsonl b/language_packs/data/en_collapse_anchors_v1/lexicon.jsonl index 4e0f5de6..5fee7f27 100644 --- a/language_packs/data/en_collapse_anchors_v1/lexicon.jsonl +++ b/language_packs/data/en_collapse_anchors_v1/lexicon.jsonl @@ -1,3 +1,11 @@ {"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"]} +{"entry_id":"en-collapse-breath","surface":"breath","lemma":"breath","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.breath"],"morphology_tags":["noun"],"provenance_ids":["adr-0073c:english_lacks_neshamah_nuance","adr-0073c:english_lacks_pnoe_neshamah_nuance"]} +{"entry_id":"en-collapse-covenant_love","surface":"covenant love","lemma":"covenant_love","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.covenant_love"],"morphology_tags":["noun"],"provenance_ids":["adr-0073a:english_lacks_chesed_lemma"]} +{"entry_id":"en-collapse-heart","surface":"heart","lemma":"heart","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.heart"],"morphology_tags":["noun"],"provenance_ids":["adr-0073c:english_lacks_kardia_leb_nuance","adr-0073c:english_lacks_leb_nuance"]} +{"entry_id":"en-collapse-holy","surface":"holy","lemma":"holy","language":"en","pos":"ADJ","semantic_domains":["collapse_anchor.holy"],"morphology_tags":["adjective"],"provenance_ids":["adr-0073c:english_lacks_hagios_qadosh_nuance","adr-0073c:english_lacks_qadosh_nuance"]} +{"entry_id":"en-collapse-shalom","surface":"shalom","lemma":"shalom","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.shalom"],"morphology_tags":["noun"],"provenance_ids":["adr-0073a:english_collapses_peace_to_absence_of_war"]} +{"entry_id":"en-collapse-soul","surface":"soul","lemma":"soul","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.soul"],"morphology_tags":["noun"],"provenance_ids":["adr-0073c:english_lacks_nephesh_nuance","adr-0073c:english_lacks_psyche_nephesh_nuance"]} +{"entry_id":"en-collapse-time","surface":"time","lemma":"time","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.time"],"morphology_tags":["noun"],"provenance_ids":["adr-0073a:english_collapses_time_family"]} +{"entry_id":"en-collapse-tzedek","surface":"tzedek","lemma":"tzedek","language":"en","pos":"NOUN","semantic_domains":["collapse_anchor.tzedek"],"morphology_tags":["noun"],"provenance_ids":["adr-0073a:english_splits_to_righteousness_justice"]} diff --git a/language_packs/data/en_collapse_anchors_v1/manifest.json b/language_packs/data/en_collapse_anchors_v1/manifest.json index 175a3c0f..867ad436 100644 --- a/language_packs/data/en_collapse_anchors_v1/manifest.json +++ b/language_packs/data/en_collapse_anchors_v1/manifest.json @@ -6,7 +6,7 @@ "normalization_policy": "unitize_versor", "source_manifest": "en_collapse_anchors_v1.lexicon.jsonl", "determinism_class": "D0", - "checksum": "bd46462611c51b93a59630085553b858dec81646e55b2864c6f040b7646d0da5", + "checksum": "e7233855ba320089d0775fe58a024e611831aae1dcdfdc7276a3f09697089f9a", "version": "1.0.0", "gate_engaged": false, "oov_policy": "passthrough", diff --git a/tests/test_workbench_logos.py b/tests/test_workbench_logos.py index 4abc28ec..1350a9a9 100644 --- a/tests/test_workbench_logos.py +++ b/tests/test_workbench_logos.py @@ -179,41 +179,39 @@ def test_invalid_alignment_target_is_listed_without_touching_engine_validators( ] == [("he-001", "ghost-target", "cross_lang.logos.utterance")] -def test_collapse_anchor_target_validity_tracks_declared_lexicon_entries() -> None: - """A declared collapse anchor resolves; an undeclared one is dangling. +def test_every_collapse_anchor_target_resolves_to_a_declared_entry() -> None: + """Every ``cross_lang.no_english_collapse`` target across the logos packs + resolves to a real declared lexicon entry — the substrate genuinely links, + not suppressed. - Regression for the removed relation/prefix carve-out: ``en-collapse-*`` - targets are valid iff they are real declared lexicon entries (e.g. - ``en-collapse-love`` in ``en_collapse_anchors_v1``). An ``en-collapse-*`` - target declared nowhere must surface as an invalid alignment target, not be - silently passed by the safety reader. + Reconciliation fix: the anchor pack (``en_collapse_anchors_v1``) now declares + the full referenced anchor set (covenant_love/shalom/tzedek + + heart/soul/breath/holy/time), so no edge dangles. This is the geometry + resolving, not the check being bypassed — the relation/prefix carve-out + stays removed. See docs/handoff/logos-collapse-anchor-reconciliation-2026-06-14.md. """ + for pack_id in ("grc_logos_cognition_v1", "he_core_cognition_v1"): + rows = logos.logos_pack_alignment(pack_id) + collapse = [r for r in rows if r.relation == "cross_lang.no_english_collapse"] + assert collapse, f"{pack_id} should declare collapse edges" + unresolved = [r.target_id for r in collapse if r.invalid_target] + assert unresolved == [], f"{pack_id} has unresolved collapse anchors: {unresolved}" - rows = logos.logos_pack_alignment("grc_logos_cognition_v1") + report = logos.logos_pack_safety(pack_id) + assert report.invalid_alignment_targets == [] + # Resolved, but never CLEAR while holonomy proof is absent (honest ceiling). + assert report.verdict is not SafetyVerdict.CLEAR + + # A previously-dangling anchor (breath) and a source-concept anchor + # (covenant_love) both resolve to the anchor pack now. by_target = { - row.target_id: row - for row in rows - if row.relation == "cross_lang.no_english_collapse" + r.target_id: r + for r in logos.logos_pack_alignment("he_core_cognition_v1") + if r.relation == "cross_lang.no_english_collapse" } - - declared = by_target["en-collapse-love"] - assert declared.invalid_target is False - assert declared.target_resolved is True - assert declared.target_pack_id == "en_collapse_anchors_v1" - - undeclared = by_target["en-collapse-breath"] - assert undeclared.invalid_target is True - assert undeclared.target_resolved is False - assert undeclared.target_pack_id is None - - report = logos.logos_pack_safety("grc_logos_cognition_v1") - invalid_target_ids = { - issue.target_id for issue in report.invalid_alignment_targets - } - assert "en-collapse-breath" in invalid_target_ids - assert "en-collapse-love" not in invalid_target_ids - assert report.verdict is SafetyVerdict.WARNING - assert report.verdict is not SafetyVerdict.CLEAR + for anchor in ("en-collapse-breath", "en-collapse-covenant_love"): + assert by_target[anchor].invalid_target is False + assert by_target[anchor].target_pack_id == "en_collapse_anchors_v1" def test_no_algebra_imports_in_workbench_logos_module() -> None: diff --git a/workbench-ui/src/app/logos/LogosRoute.test.tsx b/workbench-ui/src/app/logos/LogosRoute.test.tsx index 626d8901..0df88d1a 100644 --- a/workbench-ui/src/app/logos/LogosRoute.test.tsx +++ b/workbench-ui/src/app/logos/LogosRoute.test.tsx @@ -113,7 +113,7 @@ function contentsFor(packId: string): LogosPackContents { return { schema_version: "logos_pack_contents_v1", pack_id: packId, - manifest: { pack_id: packId }, + manifest: { pack_id: packId, role: he ? "depth_root" : "depth_relation", determinism_class: "D0" }, lexicon: [ { // grc's entry_id matches the warning safety report's dangling link. @@ -357,18 +357,21 @@ describe("LogosRoute", () => { expect(paths).toContain("/logos/packs/he_logos_micro_v1/alignment"); }); - it("renders Identity passport fields and the raw live overview projection", async () => { + it("renders Identity passport fields and the real pack manifest", async () => { stubLogosFetch(); const user = userEvent.setup(); renderRoute("/logos/he_logos_micro_v1"); await user.click(await screen.findByRole("tab", { name: "Identity" })); + // Passport fields (from the overview). expect(await screen.findByText("manifest_digest")).toBeInTheDocument(); expect(screen.getByText("source_manifest")).toBeInTheDocument(); - expect(screen.getByText("Raw overview projection")).toBeInTheDocument(); - expect(screen.getByText(/\/manifest_digest/)).toBeInTheDocument(); - expect(screen.getByText(/\/schema_version/)).toBeInTheDocument(); + // The raw viewer now shows the actual manifest (from /contents), not a + // projection of the overview. + expect(screen.getByText("Raw manifest")).toBeInTheDocument(); + expect(screen.getByText(/\/determinism_class/)).toBeInTheDocument(); + expect(screen.getByText(/\/role/)).toBeInTheDocument(); }); it("renders Safety warnings and unknown holonomy without mapping either to clear", async () => { diff --git a/workbench-ui/src/app/logos/LogosRoute.tsx b/workbench-ui/src/app/logos/LogosRoute.tsx index bd76de7d..6163876c 100644 --- a/workbench-ui/src/app/logos/LogosRoute.tsx +++ b/workbench-ui/src/app/logos/LogosRoute.tsx @@ -330,7 +330,13 @@ function OverviewTab({ overview }: { overview: LogosPackOverview }) { ); } -function IdentityTab({ overview }: { overview: LogosPackOverview }) { +function IdentityTab({ + overview, + manifest, +}: { + overview: LogosPackOverview; + manifest?: Record; +}) { return (

- Raw overview projection + {manifest ? "Raw manifest" : "Manifest (loading…)"}

- + {/* The real pack manifest from /contents — the actual passport, not a + projection. Falls back to the overview projection only while contents + is still loading. */} +
); @@ -722,7 +733,9 @@ function Workspace({ > {activeTab === "overview" ? : null} - {activeTab === "identity" ? : null} + {activeTab === "identity" ? ( + + ) : null} {isContentsTab ? (