fix(lib): don't fabricate a supporting study with no identity and no content - #99
Merged
Merged
Conversation
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
SkyeAv
force-pushed
the
skip-contentless-supporting-study
branch
from
August 14, 2026 19:03
dc8227e to
3a27ae7
Compare
5 tasks
SkyeAv
added a commit
to glusman-team/dakp
that referenced
this pull request
Aug 14, 2026
) Every DAKP edge resolves to ChemicalEntityToDiseaseOrPhenotypicFeatureAssociation, so an annotation name only reaches the edge if THAT class declares the slot. Two did not, and Tablassert's prune_to_class nulled them and stringified them into the inlined StudyResult description as "name=value": "has_supporting_studies": {"approved_treats.yaml": {..., "has_study_results": [{"id": "approved_treats.yaml#row6848", "description": "supporting_documents=<url>, <url>"}]}} Nothing in NCATSTranslator/translator-ingests models evidence that way -- there a Study is a real cohort (ICEES), dataset (COHD), trial (CTKP), or text-mining group (SemMedDB/TMKP) carrying TYPED StudyResult slots. DAKP has no studies at all: the one above is a config filename and its result a row index into a regenerated file. Both values now ride the edge in slots the class actually holds: - supporting_documents -> has_evidence. The Biolink slot is deprecated and attached to no association class. has_evidence (list[str], range information content entity) now carries BOTH DailyMed granularities -- the set label URL and the #<loinc> section URL -- from one new supporting_spl_evidence column built by spl_evidence_pipe(). It has to be one column: Tablassert applies annotations as with_columns(...alias(name)) in declaration order with no duplicate check, so a second has_evidence entry would SILENTLY overwrite the first. The per-granularity columns stay in the TSV as the debuggable split, just unannotated. - number_of_cases -> evidence_count. number_of_cases is declared on EntityToDiseaseAssociation, a SIBLING of DAKP's class rather than an ancestor, so no class carries both it and disease_context_qualifier. evidence_count is on Association itself and means the same thing for a FAERS report count. source_score keeps folding into supporting_text on purpose: has_confidence_score is mechanically available, but the column is the max NER SPAN score -- confidence that a mention was recognized, not that the statement is true -- so promoting it would mislead any consumer that weights edges by confidence. Two new config guards lock this in: annotation names must be unique per table, and every annotated Biolink slot must be one the resolved association class declares (the class is derived via derived_edge_category + resolve_association_class, not hardcoded). After this, the only thing left in the study description is the auto-derived species_context_qualifier, which Tablassert drops in a follow-up; SkyeAv/Tablassert#99 then removes the contentless struct itself. Claude-Session: https://claude.ai/code/session_014gQKmpqbfNTVPfdzYw97L2 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…content `inline_supporting_study` emitted `has_supporting_studies` unconditionally, so a section declaring no `publications` got a Study keyed by its own config filename (`my_table.yaml`) whose single StudyResult was a row index into a file the pipeline regenerates. Biolink defines `has supporting studies` as "studies that produced information used as evidence", and nothing in NCATSTranslator/translator-ingests models evidence that way -- there a Study is a real cohort (ICEES), dataset (COHD), trial (CTKP), or text-mining group (SemMedDB/TMKP) carrying typed StudyResult slots, never a key/value dump keyed by a filename. The struct is now emitted only when it carries something. A section with a real publication keeps it unchanged (`PMID:123#Table_S7 row 12` is genuine provenance), as does any section with routed UNSATISFIABLE_EDGE_FIELDS statistics or class-pruned values to preserve -- the rescue path is why the filename fallback exists at all. The sheet-name and row-number columns are consumed either way; they never reach the edge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014gQKmpqbfNTVPfdzYw97L2
SkyeAv
force-pushed
the
skip-contentless-supporting-study
branch
from
August 14, 2026 19:21
3a27ae7 to
8c5b2f7
Compare
SkyeAv
added a commit
that referenced
this pull request
Aug 14, 2026
Cut 12.0.0 and bump the package version in pyproject.toml, uv.lock, and CITATION.cff. Major, not minor: three breaking changes accumulated since 11.0.0 — the agent now builds into a caller-owned graph config instead of maintaining an internal registry (the graph_registry module, <state-dir>/graph.yaml, and the rebuild-agent-graph subcommand are gone), the QC embedding stage migrated from BioBERT to SapBERT with the model cache moving to .tablassert/sapbert/ (#93), and build-fullmap's prebuilt extraction moved into the Rust extension with force-build-contract validation before install (#97). The changelog needed restructuring, not just promoting: #93 and #97 appended their entries inside the 11.0.0 section, so the SapBERT, abbreviation-stage, and prebuilt-extraction entries are moved into 12.0.0 where they belong, and the caller-owned-graph-config change landed with no entry at all, so its breaking change (the removed --fullmap flag and rebuild-agent-graph subcommand, in-place graph mutation, orphaned registries, and the graph=/graph_path= API) is written up here. Also ships in this release: approval_ids as a curated pass-through edge field, build-kg --threads for parallel fullmap reads scaling past the 16 record shards (#101), release-mode dropping of zero effect-size edges (#95), the species_context_qualifier derivation fix, and the fix that stops fabricating a supporting study for sections with no publication and nothing to preserve (#99).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
inline_supporting_studyemittedhas_supporting_studiesunconditionally, so a section declaring nopublicationsshipped a fabricatedStudyon every edge.Changes
What was changed —
inline_supporting_studynow emits thehas_supporting_studiesstruct only when it carries something. It takes a newidentifiedargument (whetherstudy_idnames a real publication rather than falling back to the config filename), threaded fromTcode._provenance_opsasbool(publication_values). When a section is unidentified and has no routedUNSATISFIABLE_EDGE_FIELDSand no_pruned_by_classvalues, the struct is skipped. The sheet-name and row-number columns are dropped either way — they are never meant to reach the edge.Why this change is needed — Without a publication,
study_idfalls back to the config filename, so the emitted Study was keyedmy_table.yamland its singleStudyResultwas a row index into a file the pipeline regenerates:Biolink defines
has supporting studiesas "studies that produced information used as evidence". Nothing inNCATSTranslator/translator-ingestsmodels evidence this way — there aStudyis a real cohort (ICEES), dataset (COHD), trial (CTKP), or text-mining group (SemMedDB/TMKP) carrying typedStudyResultslots, never a struct keyed by a filename. Asserting a study that never existed, on every edge, is worse than emitting nothing.How it affects the project — Narrow and additive. A section with a real publication keeps the struct byte-for-byte unchanged;
PMID:123#Table_S7 row 12is genuine provenance and that is the case the feature exists for. A section with statistics to preserve also keeps it, published or not — the rescue path is the whole reason the filename fallback exists, and losing a class-refused value would be worse than naming its carrier after a config file. Only the empty-and-anonymous combination changes.Note for downstream: because
prune_to_classcreates_pruned_by_classat the schema level, any frame carrying a prunable column (today,species_context_qualifieron a class that lacks the slot) still counts as having content. Graphs will see this fix take effect once that column stops being derived.Testing
uv run pytest→ 958 passed, 1 skipped. The single failure (tests/test_agent_eval.py::test_gepa_metric_returns_prediction) is pre-existing and reproduces identically on a cleanmaincheckout.uv run ruff check .→ passed.uv run ruff format --check .→ passed.uv run pyright→ 0 errors. Coverage ofsrc/tablassert/lib.pyholds at 99% with the same six uncovered lines as baseline, so the new branch is fully exercised and no gap was introduced.inline_supporting_studytests intests/test_lib.py, covering each arm of the decision: unidentified + empty (no struct, row/sheet still consumed), unidentified + pruned statistics (struct kept, description intact), and identified + empty (struct kept, nodescriptionkey).tablassert build-kgin a downstream graph: edges lose the contentless struct while published-section edges keep theirs.Related Issues
Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_014gQKmpqbfNTVPfdzYw97L2