Skip to content

Migrate the remaining microbe-domain edges (#301, part 2 of 2) - #329

Merged
realmarcin merged 3 commits into
mainfrom
feat/301-migrate-remaining-families
Aug 6, 2026
Merged

Migrate the remaining microbe-domain edges (#301, part 2 of 2)#329
realmarcin merged 3 commits into
mainfrom
feat/301-migrate-remaining-families

Conversation

@realmarcin

Copy link
Copy Markdown
Contributor

Completes the #301 migration. MICROBE_DOMAIN_ON_NONORGANISM: 366 → 1.

What moved

The last 180 edges onto the metpo_traitmech_v9 counterparts (#326), each a 1:1 mirror
of its source predicate changing 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 180 total

Why 1 and not 0

The v9 plan said 181 → 0. It lands at 1, deliberately.

metabolism/cellulolysis.yaml carries cellulose --METPO:2000013--> cellobiose under the
label is hydrolyzed to — the same CURIE as hydrolyzes, but the inverse reading
(substrate→product, not agent→substrate). Migrating it onto METPO:2007808 would assert
cellulose 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 cellulolysis
itself, which contains both a migratable hydrolyzes edge and the excluded one: the
former moved, the latter is untouched.

The half that would have silently undone this

The 11 mapping rows still said produces → METPO:2000202 and so on, with */* gates.
Left alone, just ground-predicates would have grounded any future ungrounded edge with
those 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:

What was checked

  • just validate-strict — 477 files, 0 errors.
  • just qcgreen, every ratchet at blocking: 0.
  • uv run pytest420 passed. Ruff clean.
  • 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.
  • Evidence-snippet baseline unchanged at 2737, 0 new — the expected signature of a pass
    that reverses nothing.
  • Observed subject/object types computed from the corpus before writing each gate.

Where #301 lands

From 366 → 1. The defect class is retired except for the single edge #327 owns. The
METPO:20078xx ids remain placeholders until upstream mints them; the round-trip plan is
in proposals/metpo_traitmech_v9/proposal.md.

Note the 3 produces edges with a CHEMICAL subject (thiosulfate → sulfate and 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

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>
@culturebot-reviewer

culturebot-reviewer Bot commented Aug 6, 2026

Copy link
Copy Markdown

Claude finished @realmarcin's task in 5m 58s —— View job


Review

I verified the mechanical claims and they hold. Two findings, both about the gates, not the migration.


🟡 reducesMETPO:2007802 puts ~11 non-redox edges under an electron-donation definition

METPO:2007802 is defined in proposals/metpo_traitmech_v9/metpo_proposal_properties_robot.tsv:5 as:

asserts that the subject donates electrons to the object, lowering its oxidation state

Of the 30 edges moved onto it, roughly 11 are the "lessens" sense and assert no such thing:

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.

Fix this →


🟡 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:2007800

An 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:2000013 survives at exactly one place — cellulolysis.yaml:195, the is hydrolyzed to edge — and the neighbouring hydrolyzes edge at line 137 moved to METPO:2007808. The canary worked. No other pre-migration CURIE remains anywhere in data/traits.
  • No gate is too tight, and none is wider than the evidence. Cross-tabbed subject_type × predicate over the 180 base-report rows: every one of the 11 subject_types gates equals the observed set exactly — not a superset, not a subset. blocked_by_node_type in the residual report is 19, all from causally upstream of (13), confers (3), has output (3). The PR's claim that none of the new rows blocks anything is correct.
  • Script. MAP keyed on (predicate_id, label) is the right key given METPO:2000013's two readings, and the changed != len(targets) guard in main() 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 greenvalidate-strict, qc, pytest, label-correspondence, Curation history all 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

@culturebot-reviewer culturebot-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two 🟡 findings, both about the new mapping-row gates rather than the migration itself.

  1. reducesMETPO: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.

  2. producesMETPO:2007800: the activity-subject exclusion is spelled as three node types, so assay_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>
@realmarcin

Copy link
Copy Markdown
Contributor Author

Valid, and the node turned out to be mis-typed — so the fix makes both the gate and the data right.

🟡 The produces activity-exclusion routed around by node type

You're right that spelling the split as a subject_types exclusion of three activity types wasn't a faithful proxy. observation.yaml's assay or measurement process is typed EXPERIMENTAL_FACTOR, went around it, and landed on a term whose definition is about producing a chemical entity.

Following it up, the record contradicted its own typing twice:

  • the node's description reads "Investigation process that measures a quality";
  • it already carried a second edge, assay_measurement --has output--> measurement_datum.

So this wasn't a gate to widen — it was a node to fix. Retyped to BIOLOGICAL_PROCESS, moved the data_item edge to has output/RO:0002234, with a RETYPE_CAUSAL_NODE curation event recording why.

That also unblocked the measurement_datum edge, which had been sitting in the has output blocked-by-node-type residual — the very thing you noted made the near-miss visible in that file. 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 instead of leaning on one side's spelling. produces is 83 edges, not 84.

On your framing

Agreed that the gates are the durable artifact — that's why I went for the retype rather than adding EXPERIMENTAL_FACTOR to has output's subject types, which would have preserved the edge but broken the biolink-domain rationale that justifies routing family B upstream in the first place.

Re-verified

just qc green, just validate-strict 477 / 0 errors, uv run pytest 420 passed, ruff clean. Baseline unchanged at 1 (the #327 edge). Reports, baselines and pages/ regenerated.

@culturebot-reviewer

culturebot-reviewer Bot commented Aug 6, 2026

Copy link
Copy Markdown

Claude finished @realmarcin's task in 4m 26s —— View job


Review

Re-reviewed fd444f4d. The produces fix is right, and better than what I asked for. The reduces finding is untouched and unacknowledged, so this stays at changes-requested.


produces / has output — fixed, and fixed at the right layer

Retyping the node rather than widening the gate was the better call, and the evidence for it was already in the record. Verified:

  • assay_measurementBIOLOGICAL_PROCESS, its data_item edge on RO:0002234 (observation.yaml:91-99), and the second measurement_datum edge now grounded at :143.
  • blocked_by_node_type is 18, not 19: causally upstream of 13 + confers 3 + has output 2 (reports/predicate_grounding_residual.tsv:12,66,157). The has output row dropped from 3 to 2 and lost observation.yaml — exactly the unblock you claimed.
  • METPO:2007800 is on 83 edges in data/traits, matching the revised note. EXPERIMENTAL_FACTOR is gone from both subject_types and object_types, and since the observation edge was the only produces edge touching that type, the gates still equal the observed sets — the property I cross-tabbed last round.

🟡 reducesMETPO:2007802 still conflates redox with "lessens" (carried over, unaddressed)

Nothing changed here: mappings/predicate_grounding.tsv:93 is byte-identical, and proposals/metpo_traitmech_v9/metpo_proposal_properties_robot.tsv:5 still reads

asserts that the subject donates electrons to the object, lowering its oxidation state

with its example column still pointing at gut_associated.yaml#gut_associated_microbiota_metabolism — the peristalsis → duodenal_retention edge. Still on METPO:2007802 in the tree: cv_iodide_complex_retention (gram_variable.yaml:131), reduced_metabolic_redundancy (oligotrophic.yaml:178), proton_permeability (ph_delta_mid3.yaml:171), dna_melting_high_temperature (temperature_optimum_high.yaml:147), among ~11.

This is the same shape as the produces problem you just fixed: a gate whose spelling doesn't match the distinction it encodes, made durable for future ungrounded edges. The difference is that (predicate_id, label) can't separate these — the label is identical — so it needs a corpus relabel of the ~11 "lessens" edges onto RO:0002212 (which already has a row) before the gate can be narrowed to the redox shape, plus a corrected example column.

If you'd rather split this into its own issue than grow #329 further, that's a reasonable call — say so and I'll drop it to non-blocking. What I don't want is for it to land silently as 30 edges of precedent.

Fix this →


🔵 Three small things from the fix commit

  • metpo_proposal_properties_robot.tsv:3 still says covers 84 causal-graph edges; the corpus and the mapping note now both say 83. That annotation goes upstream with the proposal.
  • The retype trades one typing mismatch for another: CausalNodeTypeEnum.EXPERIMENTAL_FACTOR is defined in src/traitmech/schema/traitmech.yaml:494 as "An assay, perturbation, or experimental condition" — which is what a node labelled "assay or measurement process" is. There is in-corpus precedent for your reading (gram_variable.yaml types its staining procedures BIOLOGICAL_PROCESS), so I don't think it's wrong so much as the enum has no planned-process member and the corpus is already split. Worth a note somewhere rather than a change here.
  • observation.yaml:206 back-dates the RETYPE_CAUSAL_NODE event to 02:30:00Z while appending it after an 04:29:06Z entry, so the history no longer reads in order — and it reads as if the retype preceded the grounding pass that consumed it.

Otherwise

Everything I verified last round still holds: 180 + 1 excluded, the cellulolysis exclusion intact with no other pre-migration CURIE anywhere in data/traits, curation history present per file, and all 8 CI checks green (validate-strict, qc, pytest, label-correspondence, Curation history, pr-sanity, vendored-sync). Note I have no Python execution in this environment, so the counts above are grep- and report-level checks against the committed artifacts, not a re-run of the pipeline.

--- · branch feat/301-migrate-remaining-families

@culturebot-reviewer culturebot-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@realmarcin

Copy link
Copy Markdown
Contributor Author

Taking your offer to split the 🟡 — but not silently, which I read as the actual concern.

🟡 The reduces sense mismatch → #330

Real, and the same shape as the produces problem: a gate whose spelling doesn't match the distinction it encodes. Split out because fixing it needs a corpus relabel of ~11 edges onto RO:0002212 before the gate can be narrowed — and as you note, (predicate_id, label) can't separate these, since unlike #327's case the label is identical.

Filed as #330 with the full edge list. Two things I added while confirming it:

  • Object type is not a safe classifier. oxygenic_photosynthesis.yaml's photosystem I --reduces--> ferredoxin has a GENE_OR_PROTEIN object but is genuinely redox, so ~11 reduces edges use the 'lessens' sense but sit on the redox term METPO:2007802 #330 needs per-edge reading rather than a rule. Recorded in the issue so whoever picks it up doesn't write the obvious wrong filter.
  • Split is ~19 redox / ~11 lessens, matching your estimate.

Not silent precedent: the reduces mapping row now documents both senses, states plainly that the wide gate must not be read as endorsing the second, and links #330. The v9 observations cell carries the same note.

One part of it 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 doesn't describe. Repointed to environment/aerobic.yaml#aerobic_trait_mechanism (terminal_oxidases reduces molecular_oxygen).

🔵 All three fixed

  • covers 8483, matching the corpus and the mapping note after the retype.
  • Out-of-order history — right, and it read as if the retype preceded the grounding pass that consumed it. Restamped 04:35Z; curation_history now sorts correctly.
  • The enum tension — fair, and I've recorded it rather than changed anything. EXPERIMENTAL_FACTOR is defined as "An assay, perturbation, or experimental condition", which does fit that node, and CausalNodeTypeEnum has no planned-process member. The curation event now states why BIOLOGICAL_PROCESS was chosen — the node's own description calls it an investigation process, and the record already asserted has output from it, which is a process relation — and notes the corpus is already split on this.

Re-verified

just qc green, just verify-proposal PASS, just robot-validate-proposal PASS (no UNSAT), just validate-strict 477 / 0, uv run pytest 420 passed. Baseline unchanged at 1.

@culturebot-reviewer

culturebot-reviewer Bot commented Aug 6, 2026

Copy link
Copy Markdown

Claude finished @realmarcin's task in 2m 19s —— View job


Review — round 3

Re-reviewed 96c873e1. The reduces finding is resolved the way I offered, and resolved with more than a pointer. Approving.


reduces#330 — split, and not silently

I said I'd drop it to non-blocking if it went to its own issue rather than growing this PR. It did, and the durable artifacts now carry the caveat rather than just the issue tracker:

  • mappings/predicate_grounding.tsv:93 — the note now states the two senses, that ~11 edges aren't covered by the definition, that (predicate_id, label) can't separate them, and "Do not read the current wide gate as endorsing the second sense." That's the part I cared about: a future curator hitting this row can't mistake the width for a decision.
  • metpo_proposal_properties_robot.tsv:5 observations carries the same note, so it travels with the term upstream rather than staying in-repo.

The exemplar fix belonged here and is right. definition_source moved off the peristalsis edge onto environment/aerobic.yaml#aerobic_trait_mechanism, which is terminal_oxidases --reduces--> molecular_oxygen (aerobic.yaml:156-164, on METPO:2007802, described as "the four-electron reduction of O2 to water"). Genuinely redox — the term no longer illustrates itself with an edge it doesn't describe.

The observation you added to #330 is correct and worth having recorded: oxygenic_photosynthesis.yaml:150-151 is photosystem_i --reduces--> ferredoxin, GENE_OR_PROTEIN object, unambiguously redox — so object type can't classify the split. Confirmed the ~19/~11 division by reading the 33 reduces edges in the tree.


✅ The three 🔵

  • covers 8483, matching grep -c 'predicate_id: METPO:2007800$' = 83.
  • curation_history restamped 04:35:00Z, now after the 04:29:06Z grounding pass it depends on. Sorts correctly.
  • Enum tension recorded rather than changed — agreed that was the right call.

🔵 One small thing, no action needed

The RETYPE_CAUSAL_NODE event (observation.yaml:213-222) gives the affirmative case for BIOLOGICAL_PROCESS — the node's description, the pre-existing has output edge, the routed-around gate — but it doesn't actually say what it's in tension with: that CausalNodeTypeEnum.EXPERIMENTAL_FACTOR (traitmech.yaml:494) is defined as "An assay, perturbation, or experimental condition" and has no planned-process alternative. The reason to want that sentence in the record is that the next person to type an assay node will hit the same fork with the same enum. Not worth a commit on its own.


Re-verified end to end

  • Baseline is 1conf/predicate_domain_audit_baseline.tsv holds exactly the cellulolysis is hydrolyzed to row for Two opposite-direction predicate labels share METPO:2000013, so one asserts the inverse of the term's meaning #327.
  • The exclusion still holds. METPO:2000013 survives at exactly one place, cellulolysis.yaml:195. Swept all eleven pre-migration CURIEs across data/traits — no other survivor.
  • Counts. METPO:2007800 83, METPO:2007802 30 — both match their covers N annotations.
  • blocked_by_node_type is 18, unchanged from round 2: causally upstream of 13 + confers 3 + has output 2 (reports/predicate_grounding_residual.tsv:12,66,157).
  • CI: 7/7 greenvalidate-strict, qc, pytest, label-correspondence, Curation history, pr-sanity, vendored-sync.

Two caveats on my own checking: I have no Python execution here, so the counts are grep- and report-level checks against committed artifacts, not a pipeline re-run; and I can't read issues through this environment, so I verified that #330 is cited in both artifacts but not its contents.

The migration was right in round 1. What's changed since is that both gates now spell the distinction they encode, or say plainly where they don't — which was the whole of my objection.
· branch feat/301-migrate-remaining-families

@culturebot-reviewer culturebot-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant