Migrate the remaining microbe-domain edges (#301, part 2 of 2) - #329
Conversation
Moves the last 180 edges onto the causal-graph counterparts proposed in proposals/metpo_traitmech_v9, each a 1:1 mirror of its source predicate that changes only the domain, so every edge's claim and direction are unchanged: produces 84, reduces 30, oxidizes 21, exports 14, imports 12, hydrolyzes 6, degrades 6, accumulates 3, disproportionates 2, does not produce 1, transports 1 MICROBE_DOMAIN_ON_NONORGANISM: 181 -> 1. NOT 0, and the difference is deliberate. metabolism/cellulolysis.yaml carries `cellulose --METPO:2000013--> cellobiose` under the label `is hydrolyzed to`: the same CURIE as `hydrolyzes` but the inverse reading, substrate to product rather than agent to substrate. Migrating it onto METPO:2007808 would assert that cellulose hydrolyses cellobiose, so it waits on the direction decision in #327. Selection is therefore by (predicate_id, predicate LABEL), not by CURIE alone, and the exclusion is explicit in the script rather than incidental. Also repointed the 11 mapping rows, which is the half that would otherwise have silently undone this. They still mapped `produces` -> METPO:2000202 and so on with */* gates, so `just ground-predicates` would have grounded any future ungrounded edge with these labels straight back onto a microbe-domain CURIE, recreating the defect one edge at a time. Each row now targets its v9 counterpart and is gated to the node types actually observed. Two gates encode design decisions rather than just observation: - `produces` deliberately EXCLUDES the three activity node types. An activity subject belongs on RO:0002234 (has output), whose biolink domain it satisfies, so such an edge is refused here rather than routed to a METPO term duplicating an upstream one. - `hydrolyzes` is scoped to the agent-to-substrate reading, and `is hydrolyzed to` deliberately has no row at all, pending #327. Verified the new gates are not over-tight: all 19 blocked_by_node_type edges in the residual report come from pre-existing gates (`causally upstream of` 13) or part 1's rows (`confers` 3, `has output` 3). None of the 11 new rows blocks anything. validate-strict 477 files / 0 errors. Evidence-snippet baseline unchanged at 2737 with 0 new, as expected for a pass that reverses nothing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @realmarcin's task in 5m 58s —— View job ReviewI verified the mechanical claims and they hold. Two findings, both about the gates, not the migration. 🟡
|
| edge | file |
|---|---|
peristalsis → duodenal_retention |
data/traits/ecology/gut_associated.yaml |
thin_peptidoglycan_layer → cv_iodide_complex_retention |
data/traits/morphology/gram_variable.yaml:129 |
streamlined_genome → reduced_metabolic_redundancy |
data/traits/physiology/oligotrophic.yaml:176 |
c_di_amp → high_salt_tolerance |
data/traits/environment/nacl_range.yaml:152 |
compensatory_mutation → fitness_cost |
data/traits/genomics/plasmid_carriage.yaml:138 |
positive_dna_supercoiling → dna_melting_high_temperature, membrane_lipid_remodeling → inward_proton_leakage, reversed_membrane_potential → proton_influx, … |
+6 more |
Upstream METPO:2000017 carries no textual definition at all (data/raw/metpo.owl:407-411 — just an oboInOwl:hasRelatedSynonym of "reduction"), so the two senses coexisted there without contradiction. The v9 term is the first place the redox reading is written down, and this PR is where 30 edges get pointed at it. The conflation becomes an assertion here, not in #326.
The sharpest evidence that the split wasn't noticed: the term's own example column cites gut_associated.yaml#gut_associated_microbiota_metabolism — which is the peristalsis edge. A redox-only definition exemplified by intestinal transit time.
The new mapping row (mappings/predicate_grounding.tsv:93) then widens object_types to BIOLOGICAL_PROCESS|CHEMICAL|GENE_OR_PROTEIN|QUALITY and records the reason in the note — so future ungrounded reduces edges in the "lessens" sense will keep landing here. That is the same forward-looking mechanism the PR body correctly identifies as "the half that would have silently undone this," pointed the other way.
RO:0002212 (negatively regulates) already has a row in this file and is the right home for most of these. This is exactly the shape you handled correctly for hydrolyzes / is hydrolyzed to — one CURIE, two readings — except here the label is identical too, so (predicate_id, label) selection can't separate them. It needs a corpus relabel of the ~11 edges before the gate can be narrowed to the redox shape.
🟡 The produces activity-exclusion is routed around by node type
METPO:2007800's definition ends in "…and a chemical entity", but the new row's object_types admits EXPERIMENTAL_FACTOR. The edge that uses it is data/traits/upper/observation.yaml:91-99:
- subject: assay_measurement
predicate: produces
object: data_item # node_type: EXPERIMENTAL_FACTOR
predicate_id: METPO:2007800An assay producing a data item is precisely the RO:0002234 has output case your subject_types exclusion was written to divert — but the exclusion is spelled as three node types (BIOLOGICAL_PROCESS|PATHWAY|MOLECULAR_FUNCTION), and assay_measurement is typed EXPERIMENTAL_FACTOR, so it goes around the gate and lands on the chemical-production term. observation.yaml already appears in the has output blocked-by-node-type residual, which makes the near-miss visible in the same file.
The rationale in the row's note is sound; the node-type spelling of it isn't a faithful proxy for the distinction being drawn.
What checks out
- Counts exact. Recomputed the per-predicate tally from
origin/main:reports/predicate_domain_audit.tsv: 84/30/21/14/12/6/6/3/2/1/1 = 180, plus the 1 excluded. Matches the PR table. - The exclusion holds in the data.
METPO:2000013survives at exactly one place —cellulolysis.yaml:195, theis hydrolyzed toedge — and the neighbouringhydrolyzesedge at line 137 moved toMETPO:2007808. The canary worked. No other pre-migration CURIE remains anywhere indata/traits. - No gate is too tight, and none is wider than the evidence. Cross-tabbed
subject_type × predicateover the 180 base-report rows: every one of the 11subject_typesgates equals the observed set exactly — not a superset, not a subset.blocked_by_node_typein the residual report is 19, all fromcausally upstream of(13),confers(3),has output(3). The PR's claim that none of the new rows blocks anything is correct. - Script.
MAPkeyed on(predicate_id, label)is the right key givenMETPO:2000013's two readings, and thechanged != len(targets)guard inmain()is a genuine fail-safe: a triple collision between an excluded and an included edge would raise rather than migrate silently. - Curation history is written per-file with an accurate per-file breakdown; diffs are minimal and touch only
predicate/predicate_id. - CI green —
validate-strict,qc,pytest,label-correspondence,Curation historyall pass. I could not run these locally (no Python execution in this environment); I'm relying on the workflow runs.
The migration is right. Both findings are about which senses the new gates make permanent — and since the gates are the durable artifact, that's the part worth getting right before it becomes 180 edges' worth of precedent.
· branch feat/301-migrate-remaining-families
There was a problem hiding this comment.
Two 🟡 findings, both about the new mapping-row gates rather than the migration itself.
-
reduces→METPO:2007802: ~11 of the 30 migrated edges use the "lessens" sense (peristalsis → duodenal_retention, thin_peptidoglycan_layer → cv_iodide_complex_retention, streamlined_genome → reduced_metabolic_redundancy, …) but the v9 term is defined as "donates electrons to the object, lowering its oxidation state". Upstream METPO:2000017 has no definition, so this PR is where the conflation becomes an assertion — and the term's own example column cites the non-redox peristalsis edge. The widened object_types gate will keep routing future "lessens" edges here. RO:0002212 already has a row and is the right home for most. -
produces→METPO:2007800: the activity-subject exclusion is spelled as three node types, soassay_measurement produces data_item(observation.yaml:91-99, both EXPERIMENTAL_FACTOR) routes around it onto the chemical-production term — exactly the RO:0002234 has-output case the exclusion was written to divert.
Everything else verified: counts exact (180 + 1 excluded), the cellulolysis exclusion holds with zero other pre-migration CURIEs remaining, all 11 subject_types gates equal the observed sets exactly, blocked_by_node_type is 19 and all pre-existing, curation history present, CI green.
Details in the review comment.
…view) The split was spelled only as a subject_types exclusion of the three activity node types, which was not a faithful proxy for the distinction. observation.yaml's `assay or measurement process` is typed EXPERIMENTAL_FACTOR, so it routed around that exclusion and landed on METPO:2007800 -- a term whose definition is about producing a chemical entity -- when an assay producing a data item is precisely the RO:0002234 has-output case the split exists to divert. The node was mis-typed, and the record said so twice: its own description reads "Investigation process that measures a quality", and it already carried a second edge `assay_measurement --has output--> measurement_datum`. Retyped it to BIOLOGICAL_PROCESS, moved the data_item edge to has output (RO:0002234), and recorded a RETYPE_CAUSAL_NODE curation event. That also unblocked the measurement_datum edge, which had been sitting in the has-output blocked_by_node_type residual -- the same file the reviewer noted made the near-miss visible. blocked_by_node_type: 19 -> 18. With no edge using it, EXPERIMENTAL_FACTOR is now absent from BOTH subject_types and object_types on the produces row, so the gate encodes the split on both sides rather than relying on one side's spelling. produces is 83 edges, not 84. Baseline unchanged at 1 (the #327 edge). qc green, validate-strict 477/0, 420 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Valid, and the node turned out to be mis-typed — so the fix makes both the gate and the data right. 🟡 The
|
|
Claude finished @realmarcin's task in 4m 26s —— View job ReviewRe-reviewed ✅
|
There was a problem hiding this comment.
The produces/has output fix is right, and retyping the node rather than widening the gate was the better call — verified: blocked_by_node_type is now 18, METPO:2007800 is on 83 edges, and EXPERIMENTAL_FACTOR is gone from both sides of the row.
The reduces → METPO:2007802 finding from the previous round is untouched and unacknowledged: the mapping row is byte-identical, the v9 definition is still redox-only, and its example column still cites the non-redox peristalsis edge. ~11 "lessens" edges remain on it. Since the label is identical in both senses, this needs a corpus relabel onto RO:0002212 before the gate can be narrowed — or an explicit decision to split it into its own issue, which I'd accept.
Three 🔵 nits from the fix commit (stale "covers 84" in the proposal, the EXPERIMENTAL_FACTOR enum definition naming assays, an out-of-order curation_history timestamp) are in the review comment.
…(PR #329 review) The reviewer found ~11 `reduces` edges using the "lessens/decreases" sense sitting on METPO:2007802, whose v9 definition is "donates electrons to the object, lowering its oxidation state". Real, and the same shape as the produces problem: a gate whose spelling does not match the distinction it encodes. Taking the reviewer's offer to split it, because fixing it needs a corpus relabel of those edges onto RO:0002212 before the gate can be narrowed, and (predicate_id, label) cannot separate the two senses - unlike #327's case, the label is identical. Filed as #330 with the full edge list. But NOT silently, which was the reviewer's actual concern. The reduces mapping row now documents both senses, says the wide gate must not be read as endorsing the second, and links #330. The v9 observations cell carries the same note. One part did belong here: METPO:2007802's definition_source cited the non-redox peristalsis edge as its exemplar, so the artifact going upstream illustrated the term with an edge the term does not describe. Repointed to environment/aerobic.yaml#aerobic_trait_mechanism (terminal_oxidases reduces molecular_oxygen), which is redox. Worth recording: object type is NOT a safe classifier for the two senses. oxygenic_photosynthesis's `photosystem I reduces ferredoxin` has a GENE_OR_PROTEIN object but is genuinely redox, so #330 needs per-edge reading rather than a rule. Three smaller review items: - v9 produces row said "covers 84 causal-graph edges"; corpus and mapping note both say 83 after the observation.yaml retype. Now 83. - The RETYPE_CAUSAL_NODE event was back-dated to 02:30Z but appended after an 04:29Z entry, so history read out of order and implied the retype preceded the grounding pass that consumed it. Restamped 04:35Z; curation_history is now sorted. - Recorded the enum tension rather than hiding it: EXPERIMENTAL_FACTOR is defined as "An assay, perturbation, or experimental condition", which also fits that node, and CausalNodeTypeEnum has no planned-process member. The corpus is already split - gram_variable types its staining procedures BIOLOGICAL_PROCESS. The event now says why BIOLOGICAL_PROCESS was chosen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Taking your offer to split the 🟡 — but not silently, which I read as the actual concern. 🟡 The
|
|
Claude finished @realmarcin's task in 2m 19s —— View job Review — round 3Re-reviewed ✅
|
There was a problem hiding this comment.
The reduces finding is resolved the way I offered — split to #330, and not silently: the mapping row (line 93) and the v9 observations cell both now state the two senses and say plainly that the wide gate must not be read as endorsing the second. The part that belonged here was the exemplar, and it's fixed correctly — METPO:2007802's definition_source now points at aerobic.yaml#aerobic_trait_mechanism (terminal_oxidases reduces molecular_oxygen), a genuinely redox edge.
Verified: baseline is 1 (the #327 cellulolysis edge, sole surviving pre-migration CURIE across all eleven); METPO:2007800 on 83 edges and METPO:2007802 on 30, both matching their covers N annotations; blocked_by_node_type still 18; curation_history restamped 04:35Z and now in order; covers 84 -> 83. CI 7/7 green.
One 🔵 not worth a commit: the RETYPE_CAUSAL_NODE event gives the affirmative case for BIOLOGICAL_PROCESS but doesn't record what it's in tension with — that CausalNodeTypeEnum.EXPERIMENTAL_FACTOR is defined as "An assay, perturbation, or experimental condition" and the enum has no planned-process member. The next person to type an assay node hits the same fork.
Caveats on my checking: no Python execution here, so counts are grep- and report-level against committed artifacts rather than a pipeline re-run; and I can't read issues, so I confirmed #330 is cited in both artifacts but not its contents.
Details in the review comment.
Completes the #301 migration.
MICROBE_DOMAIN_ON_NONORGANISM: 366 → 1.What moved
The last 180 edges onto the
metpo_traitmech_v9counterparts (#326), each a 1:1 mirrorof its source predicate changing only the domain — so every edge's claim and direction are
unchanged:
Why 1 and not 0
The v9 plan said 181 → 0. It lands at 1, deliberately.
metabolism/cellulolysis.yamlcarriescellulose --METPO:2000013--> cellobioseunder thelabel
is hydrolyzed to— the same CURIE ashydrolyzes, but the inverse reading(substrate→product, not agent→substrate). Migrating it onto
METPO:2007808would assertcellulose hydrolyses cellobiose. It waits on the direction decision in #327.
Selection is therefore by (predicate_id, predicate label), not CURIE alone, and the
exclusion is explicit in the script rather than incidental. Canaried on
cellulolysisitself, which contains both a migratable
hydrolyzesedge and the excluded one: theformer moved, the latter is untouched.
The half that would have silently undone this
The 11 mapping rows still said
produces → METPO:2000202and so on, with*/*gates.Left alone,
just ground-predicateswould have grounded any future ungrounded edge withthose labels straight back onto a microbe-domain CURIE, recreating the defect one edge
at a time. Each row now targets its v9 counterpart and is gated to the observed node types.
Two gates encode decisions rather than just observation:
producesexcludes the three activity node types. An activity subject belongs onRO:0002234(has output), whose biolink domain it satisfies — so such an edge isrefused here rather than routed to a METPO term duplicating an upstream one.
hydrolyzesis scoped to the agent→substrate reading, andis hydrolyzed tohas norow at all, pending Two opposite-direction predicate labels share METPO:2000013, so one asserts the inverse of the term's meaning #327.
What was checked
just validate-strict— 477 files, 0 errors.just qc— green, every ratchet atblocking: 0.uv run pytest— 420 passed. Ruff clean.blocked_by_node_typeedges in the residualreport come from pre-existing gates (
causally upstream of13) or part 1's rows(
confers3,has output3). None of the 11 new rows blocks anything.that reverses nothing.
Where #301 lands
From 366 → 1. The defect class is retired except for the single edge #327 owns. The
METPO:20078xxids remain placeholders until upstream mints them; the round-trip plan isin
proposals/metpo_traitmech_v9/proposal.md.Note the 3
producesedges with a CHEMICAL subject (thiosulfate → sulfateand similar)are migrated as-is but are the same chemistry-transformation shape as #327's edge — flagged
in the mapping row's note rather than silently absorbed.
🤖 Generated with Claude Code