Skip to content

Activate the MONDO close-match guard in disease glom (with build-vs-build clique-diff tool)#883

Closed
gaurav wants to merge 3 commits into
add-mpofrom
fix-mondo-close-match-guard
Closed

Activate the MONDO close-match guard in disease glom (with build-vs-build clique-diff tool)#883
gaurav wants to merge 3 commits into
add-mpofrom
fix-mondo-close-match-guard

Conversation

@gaurav

@gaurav gaurav commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Important

Superseded by #888. The MONDO close-match guard fix has been split onto a clean,
main-based branch in #888 (the same x[1]x[2] change applied directly to
build_compendium, plus a focused regression test), and the build-vs-build clique-diff tool
already merged separately via #885. If #888 merges first, this guard change drops out of this
PR automatically once main is merged in — leaving #883 with nothing unique to contribute.
Prefer reviewing #888 for the guard fix in isolation; this PR is kept only as the home of the
full add-mpo-base before/after impact analysis under
docs/pipelines/diseasephenotype/mondo-close-match-guard/.

Summary

Fixes a latent bug in how the disease/phenotype build reads the MONDO_close concord, which
left glom's close-match guard a silent no-op, and adds a reusable build-vs-build clique-diff
tool plus the before/after impact analysis that this change requires.

This is the dedicated follow-up promised in #790, where the same code was touched only enough to
stop the build crashing (validating the real 3-column MONDO_close format while preserving
the dormant x[1] behaviour). Activating the guard changes disease clique merging broadly and is
orthogonal to adding MP, so it lives here with its own evidence.

Note

Based on add-mpo (#790), not main — it builds on that PR's compute_cliques_for_impact_report
refactor. Merge #790 first; this PR will retarget to main automatically.

The bug

compute_cliques_for_impact_report() read MONDO_close (a 3-column subject predicate object
concord) with close_mondos[x[0]].add(x[1]) — keying the MONDO subject to column 2, the
predicate
(oio:closeMatch) instead of column 3, the close-match object. No clique ever
contains the literal string oio:closeMatch, so glom's close= guard (if cd in newset) never
matched. The guard has therefore never fired, on main and before it; close (but not exact)
matches were free to collapse into exact cliques.

The fix is one line of intent: key on x[2], matching the (stuff[0], stuff[2]) parsing every
other concord in that function already uses.

Impact (why this needs SME review)

Measured on a full local disease build (Biolink 4.4.3), same intermediate ids/concords,
differing only in x[1] vs x[2]. glom is deterministic — two x[1] builds were clique-identical
— so every difference is signal, not run-to-run noise.

  • 1,219 identifiers, all MEDDRA, are dropped from Disease.txt. They were present only because
    the dormant guard let them merge into a MONDO disease clique; correctly kept out, they have no
    independent disease typing in this pipeline and leave the compendium entirely.
  • 1,191 of 365,465 Disease cliques lose ≥1 member; net Disease clique count +20, PhenotypicFeature +13.
  • PhenotypicFeature.txt is essentially unaffected (the close pairs are MONDO-subject).

Dropping 1,219 MEDDRA codes is correct if they are genuinely distinct concepts (the guard's
premise), but a coverage loss if anything relies on that MEDDRA → MONDO normalization. Per the
project rule against dropping valid identifiers without good reason, this is an SME call — the
evidence is in docs/pipelines/diseasephenotype/mondo-close-match-guard/ (README.md,
clique-diff.csv, dropped-members.csv, summary.json).

New tool: babel-clique-diff

A reusable build-vs-build clique diff (tools/clique_diff) that compares the finished compendia of
two builds and reports split/merged/lost cliques and, crucially, dropped CURIEs.

It is deliberately distinct from source-impact-report: that answers "what does adding source
X
do?" by re-glomming intermediates with vs. without one source; this answers "how did the cliques
change between build A and build B?" given the same inputs but different code/config/data.
Because it works on finished compendia rather than glom state, it can also compare a local build
against a published stars.renci.org build with no re-glom — useful for validating any glom-logic
change (close-match, unique_prefixes, overuse filtering) or as a release regression check.

Test plan

  • uv run ruff check / ruff format --check — clean.
  • uv run rumdl check . — clean.
  • uv run pytest -m unit -q — green (243 passed), including new tests/tools/test_clique_diff_tool.py.

Out of scope

🤖 Generated with Claude Code

gaurav and others added 3 commits June 29, 2026 19:40
A new tools/clique_diff package + `babel-clique-diff` entry point that compares the
finished JSONL compendia of two builds and reports which cliques split/merged/lost
members, and — the headline signal — which CURIEs were dropped from the output entirely.

This is distinct from source-impact-report: that answers "what does adding source X do?"
by re-glomming intermediate files with vs. without one source; this answers "how did the
cliques change between build A and build B?" given the same inputs but different code,
config, or upstream data. It works on finished compendia rather than glom state, so it can
also compare a local build against a published stars.renci.org build without re-running
glom — useful for validating any glom-logic change or as a release regression check.

Includes unit tests for the four destination kinds (kept/regrouped/moved/dropped) and a
docs/tools/README.md entry. The test module has a unique basename (test_clique_diff_tool)
to avoid a pytest prepend-mode collision with tests/test_clique_diff.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
compute_cliques_for_impact_report() read MONDO_close with close_mondos[x[0]].add(x[1]),
keying the MONDO subject to column 2 (the predicate, "oio:closeMatch") instead of column 3
(the close-match object). No clique ever contains the literal predicate string, so glom's
`close=` guard never matched and was a silent no-op on every build, letting close (but not
exact) matches collapse into exact cliques. Key on x[2] instead, matching the
(stuff[0], stuff[2]) parsing every other concord in this function already uses.

Activating the guard is a deliberate, SME-reviewable change: on a full local disease build
it drops 1,219 MEDDRA identifiers from Disease.txt (present only via the dormant guard's
incorrect close-as-exact merges). The before/after impact analysis and the SME-facing
dropped-members list are committed under
docs/pipelines/diseasephenotype/mondo-close-match-guard/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generated by babel-clique-diff against two full local disease builds (x[1] dormant guard
vs x[2] active guard), differing only in the one-line MONDO_close parsing fix. glom is
deterministic (two x[1] builds were clique-identical), so the diff is all signal.

- README.md — the bug, the fix, and the SME decision (1,219 MEDDRA codes leave Disease.txt).
- clique-diff.csv — every changed clique with destination_kind (kept/regrouped/moved/dropped).
- dropped-members.csv — the 1,219 dropped CURIEs with the MONDO clique each left.
- summary.json — per-compendium counts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gaurav added a commit that referenced this pull request Jun 29, 2026
Cross-link the deferred x[1]->x[2] close-match-guard fix to its dedicated PR (#883), and
note the concrete impact (~1,219 MEDDRA identifiers dropped from Disease.txt) that the
follow-up's before/after analysis quantifies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gaurav

gaurav commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

Heads up: the babel-clique-diff tool commit from this PR has been extracted into its own standalone PR off main (#885) so it can land independently of the MONDO close-match-guard change here. Once #885 merges, please rebase this PR to drop its now-duplicated babel-clique-diff commit. The new "MP kept disjoint from HP" PR (#886) depends on #885.

gaurav added a commit that referenced this pull request Jun 30, 2026
The extracted babel-clique-diff commit linked to #883's mondo-close-match-guard
evidence dir, which is not present on this standalone tool branch. Replace it with
the general commit-location convention for clique-diff outputs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gaurav added a commit that referenced this pull request Jun 30, 2026
Cross-link the deferred x[1]->x[2] close-match-guard fix to its dedicated PR (#883), and
note the concrete impact (~1,219 MEDDRA identifiers dropped from Disease.txt) that the
follow-up's before/after analysis quantifies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gaurav added a commit that referenced this pull request Jun 30, 2026
Add docs/sources/MP/disjointness.md explaining the post-glom split, why
unique_prefixes/concord-dropping are insufficient, and the measured impact
(added/split/moved/deleted) from babel-clique-diff comparing the overlap-allowed
build to the disjoint build. Commit the clique-diff CSV + summary JSON under
docs/sources/MP/disjointness/. Update the MP and HP READMEs: MP/HP are now disjoint,
so an MP clique carries only the Mammalia taxon and an HP clique only Homo sapiens
(correcting the earlier "mixed cliques carry both taxa" note). Cross-link prior PRs
(#790, #300, #883, #742/#781).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gaurav added a commit that referenced this pull request Jul 2, 2026
Adds `babel-clique-diff`, a build-vs-build clique diff tool that
compares the cliques in two
finished Babel compendium builds and reports, per `(changed
before-clique, after-destination)`
group, whether members were `kept`, `regrouped` (split into a different
clique), `moved` (retyped
into a different compendium file), or `dropped` (absent from every
compared after-compendium). It
emits a per-clique CSV and an optional per-compendium summary JSON (with
`dropped_member_count` /
`regrouped_member_count` as the headline regression signals).

```
uv run babel-clique-diff \
    --before <baseline-compendia-dir> --after <comparison-compendia-dir> \
    --files Disease.txt PhenotypicFeature.txt \
    --out-csv clique-diff.csv --out-json clique-diff.summary.json
```

Unlike `source-impact-report` (which is hard-wired to an "exclude one
source" before/after and only
models added/expanded/merged cliques), this tool diffs **two arbitrary
builds** and can express
**splits and deletions** — needed whenever a config/policy change
regroups or drops members of
existing cliques rather than just adding new ones.

## Provenance / coordination

This is the `babel-clique-diff` commit extracted from PR #883
(`fix-mondo-close-match-guard`), so it can land independently of #883's
unrelated MONDO
close-match-guard change. It is stdlib-only and purely additive (new
`tools/clique_diff/` package,
a unit test, and one `[project.scripts]` entry).

- **Merge this before** the follow-up "MP kept disjoint from HP" PR,
which uses this tool to produce
  its split/deleted impact report.
- **#883 should rebase** to drop its now-duplicated `babel-clique-diff`
commit once this merges.

## Test plan

- `uv run pytest tests/tools/test_clique_diff_tool.py -q` — green (5
passed): the four destination
kinds (kept/regrouped/moved/dropped), the cross-file moved-vs-dropped
distinction, the
  unchanged-cliques-omitted rule, and malformed-JSONL rejection.
- `uv run pytest -m unit -q` — green (241 passed), collects cleanly
(unique test basename, no
  `tests/tools/__init__.py`).
- `uv run babel-clique-diff --help` — console script resolves.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
gaurav added a commit that referenced this pull request Jul 2, 2026
The NOTE in compute_cliques_for_impact_report and disjointness.md's "Related
work" pointed the deferred close-match-guard fix at the old combined PR #883.
That PR was split: the babel-clique-diff tool is now #885 and the close-match
guard activation (keying glom's close= map on the object, x[2], rather than the
predicate, x[1]) is now #888 (fix-mondo-close-guard). Point both references at
the concrete PRs so they don't go stale. No behavior change -- this branch still
preserves the predicate-keyed no-op that #888 will fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gaurav added a commit that referenced this pull request Jul 10, 2026
Build-vs-build diff isolating the close-match guard activation (#888,
issue #912): both compendia built from identical cached disease
intermediates, differing only in diseasephenotype.py keying close_mondos
on the object (x[2]) vs the predicate (x[1]).

Result: 1,218 MEDDRA identifiers drop from Disease.txt (the close-match
terms that reached MONDO cliques via the UMLS concord), matching the
~1,219 figure from #883. PhenotypicFeature.txt is essentially unaffected.

Indexes the new docs/sources/MONDO entry in docs/sources/README.md and
CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gaurav gaurav added this to the Babel v1.18 milestone Jul 12, 2026
@gaurav

gaurav commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Closing: everything in this PR now lives either in main or in #888.

Verified against main (9058e63) and #888 (fix-mondo-close-guard):

  • babel-clique-diff tool (tools/clique_diff/, pyproject.toml entry point, docs/tools/README.md, tests/tools/test_clique_diff_tool.py) — merged via Add babel-clique-diff: build-vs-build compendium clique diff tool #885, in a better shape than here: the diff logic now lives in src/model/compendium_diff.py with src/tools/clique_diff/cli.py as a thin CLI, and the tests moved to tests/tools/clique_diff/test_cli.py.
  • The MP base this branch was stacked on (Add MP (Mammalian Phenotype Ontology) as a disease/phenotype source #790, since closed) — the MP source, its docs under docs/sources/MP/, and tests/pipeline/test_mp_pipeline.py are all in main.
  • The guard fix itself (close_mondos[x[0]].add(x[1])x[2]) — carried by Activate glom's MONDO close-match guard, with concord-reader symmetry tests #888, applied directly to build_compendium on a clean main base, with 164 lines of new concord-reader symmetry tests in tests/createcompendia/test_diseasephenotype.py that this PR did not have.
  • The before/after impact analysis (docs/pipelines/diseasephenotype/mondo-close-match-guard/) — superseded by docs/sources/MONDO/mondo-close-match-guard/ on Activate glom's MONDO close-match guard, with concord-reader symmetry tests #888, which is a strict superset: same clique diff (1,218 dropped MEDDRA identifiers, matching the ~1,219 reported here), plus the split-cliques.csv analysis of the 37 cliques that structurally split — the changes that actually need SME review — and the explanation of why glom() ejects a legitimate non-MEDDRA identifier as collateral damage when the guard fires.

The one file with no direct counterpart on #888 is dropped-members.csv, but it is redundant: all 1,218 dropped CURIEs are fully enumerated (no truncation) in the example_members column of #888’s clique-diff.csv, keyed to the MONDO clique each left.

Nothing needs cherry-picking. The guard fix continues on #888.

@gaurav gaurav closed this Jul 12, 2026
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Babel sprints Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant