Merge pull request #743 from AssetOverflow/codex/logos-collapse-anchor-reconciliation
fix(logos): collapse-anchor reconciliation (alignment resolves) + Identity real manifest
This commit is contained in:
commit
86f25dc9ce
5 changed files with 62 additions and 40 deletions
|
|
@ -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"]}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 () => {
|
||||
|
|
|
|||
|
|
@ -330,7 +330,13 @@ function OverviewTab({ overview }: { overview: LogosPackOverview }) {
|
|||
);
|
||||
}
|
||||
|
||||
function IdentityTab({ overview }: { overview: LogosPackOverview }) {
|
||||
function IdentityTab({
|
||||
overview,
|
||||
manifest,
|
||||
}: {
|
||||
overview: LogosPackOverview;
|
||||
manifest?: Record<string, unknown>;
|
||||
}) {
|
||||
return (
|
||||
<div className="grid gap-4">
|
||||
<MetadataTable
|
||||
|
|
@ -357,9 +363,14 @@ function IdentityTab({ overview }: { overview: LogosPackOverview }) {
|
|||
/>
|
||||
<section>
|
||||
<h3 className="m-0 mb-2 text-xs font-semibold text-[var(--color-text-secondary)]">
|
||||
Raw overview projection
|
||||
{manifest ? "Raw manifest" : "Manifest (loading…)"}
|
||||
</h3>
|
||||
<StableJsonViewer source={JSON.stringify(overview, null, 2)} />
|
||||
{/* The real pack manifest from /contents — the actual passport, not a
|
||||
projection. Falls back to the overview projection only while contents
|
||||
is still loading. */}
|
||||
<StableJsonViewer
|
||||
source={JSON.stringify(manifest ?? overview, null, 2)}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -722,7 +733,9 @@ function Workspace({
|
|||
>
|
||||
<TabBar tabs={LOGOS_TABS} activeTab={activeTab} onTabChange={setActiveTab}>
|
||||
{activeTab === "overview" ? <OverviewTab overview={overview} /> : null}
|
||||
{activeTab === "identity" ? <IdentityTab overview={overview} /> : null}
|
||||
{activeTab === "identity" ? (
|
||||
<IdentityTab overview={overview} manifest={contents?.manifest} />
|
||||
) : null}
|
||||
{isContentsTab ? (
|
||||
<ContentsGate
|
||||
tab={activeTab}
|
||||
|
|
|
|||
Loading…
Reference in a new issue