You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #350. Depends on #351 and #354; best done after #357 has landed real facts.
121 species out of 489,358 have an edible_part. Even the best sources available (#356) top out around 40,000 species with a food-use record, and most of those are not in our accepted-name set. Crawling species by species will not close a 489,000-row gap, ever.
Edibility is strongly heritable, and that is the lever. Every Rubus has an edible fruit. Every Allium has edible leaves and bulbs. Ribes, Vaccinium, Prunus (fruit edible, seed cyanogenic — the toxic side inherits too). Propagating a well-sourced genus-level claim down to its species is how coverage goes from 0.05 % to something a client can build on.
The infrastructure already exists: SpeciesFact has evidence_type: inferred — "imputed (e.g. from congeneric species)" — sitting unused (app/models/species_fact.rb:16). This issue is what fills it.
For each genus, aggregate the active edibility facts of its species. Emit a genus-level claim only above a support threshold — a proposal to start from: at least 3 species with facts, and at least 80 % agreement on the part. Tune against the real distribution and report the curve before running.
Propagate to species in that genus that have no fact for the attribute, as evidence_type: inferred, source: "trefle:congeneric", with notes naming the species the inference came from.
Never overwrite. An inferred fact loses to any reported or measured fact, and must never be projected onto a column that already holds a sourced value.
A later real fact for a species supersedes its inferred one; re-running the worker after new source data must converge, not accumulate. Idempotence is the hard requirement here.
Public exposure — the part that makes this safe to ship:
Each edibility claim in the payload carries its evidence level (measured / reported / derived / inferred).
filter[evidence]=reported,measured lets a caller exclude everything inferred. A recipe app takes hard evidence only; an exploration UI happily shows "probably edible, inferred from 12 congeners".
The species page shows inferred values differently from sourced ones, with the congeners named.
The completion ratio (Species#current_completion_percentage) must not count inferred facts as filled, or we lose the map of what still needs real sourcing.
Acceptance
Worker specs: threshold respected, never overwrites a sourced fact, idempotent across re-runs, converges when a real fact arrives later.
A dry-run report posted here — species gained per attribute, genus count, the agreement-threshold curve — before any write to the dev DB, and again before prod.
Request specs for filter[evidence].
A spot-check list of ~30 inferred species reviewed by hand against a reference before the prod run. Publishing 300,000 machine-guessed edibility claims without a human ever looking at a sample is not something to do on spec coverage alone.
Part of #350. Depends on #351 and #354; best done after #357 has landed real facts.
121 species out of 489,358 have an
edible_part. Even the best sources available (#356) top out around 40,000 species with a food-use record, and most of those are not in our accepted-name set. Crawling species by species will not close a 489,000-row gap, ever.Edibility is strongly heritable, and that is the lever. Every Rubus has an edible fruit. Every Allium has edible leaves and bulbs. Ribes, Vaccinium, Prunus (fruit edible, seed cyanogenic — the toxic side inherits too). Propagating a well-sourced genus-level claim down to its species is how coverage goes from 0.05 % to something a client can build on.
The infrastructure already exists:
SpeciesFacthasevidence_type: inferred— "imputed (e.g. from congeneric species)" — sitting unused (app/models/species_fact.rb:16). This issue is what fills it.Scope
Inference worker (
app/workers/migrators/pattern, replayable, dry-runnable):evidence_type: inferred,source: "trefle:congeneric", withnotesnaming the species the inference came from.reportedormeasuredfact, and must never be projected onto a column that already holds a sourced value.severityon a plant nobody checked is exactly the failure mode Toxicity is an enum filled on 0 of 489k species: populate it, and model it per part like edibility #355 exists to avoid. Inference on the toxic side may only ever raise a warning, never clear one.Public exposure — the part that makes this safe to ship:
measured/reported/derived/inferred).filter[evidence]=reported,measuredlets a caller exclude everything inferred. A recipe app takes hard evidence only; an exploration UI happily shows "probably edible, inferred from 12 congeners".Species#current_completion_percentage) must not count inferred facts as filled, or we lose the map of what still needs real sourcing.Acceptance
filter[evidence].Touches:
app/workers/migrators/,app/models/species_fact.rb,app/serializers/,app/controllers/api/v1/species_controller.rb,lib/schemas/v1/,spec/