Biodiversity Drift + Ecoregion Match #20
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally filed by @coilysiren on 2026-05-02T23:10:19Z
Task 10 — Biodiversity Drift + Ecoregion Match
Prereq: read
todo/README.mdfirst.Goal
Build an MCP tool
get_eco_ecoregionrendering a card that:Data sources
Public:
GET http://eco.coilysiren.me:3001/api/v1/worldlayers/layers— list of 7 top-level categories. Each entry:{Category, List: [{LayerName, LayerDisplayName, Summary, Tooltip, Category, DisplayRow}]}."Biome"and"Animal". Check the other category strings before assuming"Plant Group"is one of them — pull the distinctCategoryvalues from the response first.TaigaBiome,DesertBiome,WetlandBiome,ColdForestBiome,ForestBiome,WarmForestBiome,TundraBiome,DeepOceanBiome,OceanBiome,GrasslandBiome,RainforestBiome,IceBiome— 12 total.Summaryis a string like"4%". Parse withfloat(re.match(r"(\d+(?:\.\d+)?)", summary).group(1)).Admin (header
X-API-Keyfrom SSM/eco-mcp-app/api-admin-token, regionus-east-1):GET /api/v1/exporter/specieslist— newline-delimited plain text, NOT JSON. Parseresp.text.splitlines().GET /api/v1/exporter/species?speciesName=X— CSV"Time","Value".Timeis seconds since cycle start (600 s cadence).Static, committed in-repo:
data/ecoregions.json(don't fetch at runtime). Source candidates:https://ecoregions.appspot.com/(manual download) or WWF's Terrestrial Ecoregions of the World publication. Shape:[{name, biome_vector: {TaigaBiome: 0.0, DesertBiome: 0.15, ...}, description}, ...].IMPORTANT: biome percentages do NOT sum to 100
In live data (verified today):
The summaries are % of world area, but large chunks of the world (mountains, shallow water, transitional zones) don't fall into any named biome. Normalize the vector to
sum=1.0before doing cosine similarity with the WWF vectors. Do not assert on raw-sum >= 95%.Card layout
sim(a, b) = dot(a, b) / (norm(a) * norm(b)).(latest − first) / firstdelta.Dead-end (do not attempt)
Rendering world biomes as spatial tiles. The per-layer endpoint only returns summary text, no grid pixels — verified dead in a prior spike. This tool works from percentages only.
Implementation notes
worldlayers/layersresponse for 5 minutes — biome percentages don't change minute-to-minute.Acceptance
boomandbustlists; on Day 3 both lists may have near-zero deltas — render "drift minimal so far" as a placeholder in that case.ecoregions.json.inv smokepasses.Migrated from coilyco-flight-deck/eco-mcp-app#6 during the eco repo consolidation (coilysiren/inbox#100).
🔒 Reserved by
ward agent --driver claude— containerengineer-claude-eco-app-20on hostKAI-DESKTOP-TOWERis carrying this issue (reserved 2026-07-05T04:37:28Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).
— Claude (she/her), via
ward agentWARD-OUTCOME: done - shipped the
/ecoregionSPA surface forget_eco_ecoregionand fixed an inf-delta JSON crash the new endpoint would have hit.Honest retro: most of this tool was already here. The MCP side (
ecoregion.py, the card, the committed WWF fixture, its tests) rode in with the repo consolidation, so the real gap was the product surface - every sibling tool has an SPA page and this one didn't, which is what kept the issue open under the "product UX is the SPA" doctrine. Copying the Climate/Crafting page pattern made that part smooth.What fought back: a latent bug the SPA route exposed. A species growing from a zero baseline yields
deltaRel=inf, and Starlette'sJSONResponserejectsinfoutright, so/preview/get_eco_ecoregion.jsonwould have 500'd in production. I only caught it by checking the serialization before trusting it. Fixed it at the payload boundary (deltaRel=null+ afromZeroflag, rendered as "new" in all three consumers) and drove the real HTTP route with a from-zero grower to confirm the 200.Confidence is high on the code - 404 python + 58 frontend tests green, lint/build/smoke clean, and the concurrent
/replaylanding that raced me to main merged cleanly. One caveat: I could not reach the live game server from the container, so I validated against mocked upstream rather than real biome percentages - worth an eyeball on the donut once it deploys. Possible follow-up: the SPA donut shows raw percents with an explicit unclassified slice (per the issue acceptance) while the older in-chat MCP card shows normalized classified-share, so the two surfaces diverge on that choice and might be worth reconciling.