QA sweep 2026-08-13: remaining verified findings across the 25-tool MCP surface #270
Labels
No labels
burndown-2026-06
headless
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/eco-app#270
Loading…
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?
Collector for findings from an independent QA pass over all 25 Eco MCP tools at
5e05296, run 2026-08-13 18:21–18:30 UTC — sixteen minutes after that commit was pushed. Criticals are filed separately as #266, #267, #268, #269; this issue holds everything else so it does not get lost.Coverage caveat, stated plainly: 71 calls across 25 tools. Eight tools reached five calls; seventeen did not. Several tools return 30–60 KB per call even with
limitset, so exhaustive per-tool repetition did not fit one context. Breadth was chosen over depth. That payload size is #267.No regressions found. Everything I retested from the 2026-08-12 and 2026-08-13 fix waves still works:
get_civicsid handling,get_mapseam flags,find_tradeitem matching,get_storesmixed-currency flagging,get_recipesindexScope,get_socialreputation columns,get_marketrebuild,get_milestonesculture reconciliation.Correctness
get_climateheadline contradicts its own explainer.status: "warming"and narrative "Climate is warming" alongside an explainer reading "CO2 sits at 325 ppm — pinned to the simulation floor, the cleanest the atmosphere can get" and "the current trajectory is safe", withtemperature.rate_per_day: 0. A caller readingstatusand a caller readingexplainerreach opposite conclusions.get_regionlabels a growing population "declining".WheatSpecieshaschangePct: +0.454(500 → 727 across the cycle) withstate: "declining"and reason "Population is declining, but the combined at-risk threshold was not crossed." The recent window is down 17%, which is what the classifier keyed on — butstableentries carry the qualifier "…but the population is still well down across the cycle", and the mirror-image qualifier is missing here.32db802made the classifier signed; the reason string did not follow.get_region.sharePercentsilently excludes water.CoastalWateris the single largest biome atpercent: 36but reportssharePercent: 0; shares are computed over the 39% land subtotal only. A caller readingsharePercentconcludes Ocean (33.3%) leads and CoastalWater is absent.percent,rawSumPercent,classifiedPercentandunclassifiedPercentall reconcile correctly — onlysharePercentneeds a denominator note or a rename.get_progressiontimelines are undeduplicated and non-monotonic. One citizen'scharacterLevel: 10with a timeline descending 8, 8, 7, 7, 6, 6, 5, 5, 4, 4 in reverse-chronological order, then level 10 at day 17 and level 8 at day 14. Every level appears twice.get_civicsexplicitly dedupes this same exporter's repeated rows (132e0c2,2357c0b) and documents it;get_progressiondoes not.get_speciesfabricates identity for unknown input.get_species(name="NotASpeciesZZZ")returnsname: "Not A Species Z Z Z"(input mangled by splitting on capitals),speciesId: "NotASpeciesZZZSpecies"(an id invented for a species that does not exist), anderror: "population unavailable (HTTP 500)"— a raw upstream 500, with nonot_foundflag.explain_itemhandles the same case correctly withnot_found: true; copy that shape.get_speciestaxonomy rank/name mismatch.Bisonreturns{"rank": "Genus", "name": "Cattle and bison"}. That is the iNaturalist vernacular for tribe Bovini; the genus is Bison.find_tradecounts unbuyable offers and mislabels a supply gap. Offers withquantity: 0appear in bothcheapestandresale. OnesupplyGapsentry is labelledreason: "thin_supply"withdemandQty: 0andsupplyQty: 147— that is excess supply, not thin supply. Separatelyarbitrage: []is returned with no explanation while Iron Bar sells at 0.26 in one currency and bids at 1.00 in another; if cross-currency arbitrage is deliberately excluded, say so in the payload.trade_watcherscompares prices across unlike currencies. An "under 0.85" threshold is applied to trades spanning two currencies, andtotalVolumesums them.get_storesflags exactly this withmixedCurrencyVolume(48ca4d7) andfind_tradesegments by currency;trade_watchersdoes neither.Naming and disclosure
get_server_status.activeAndOnlineis not "online". Default server:online: 0,onlineNames: [],activeAndOnline: 7. Cross-check ondaokingdom.eu:3001:online: 27with 27 names,activeAndOnline: 62. The field is Eco's ActivePlayers; the name asserts a conjunction the data contradicts.get_server_status.animalsNoteis factually stale. It reads "Upstream /info reports 0 animals on every server observed, including ones with live fauna".daokingdom.eu:3001returnedanimals: 773in the same batch. The note fromf7a12a2is right to exist; its universal claim is now false.explain_item.image_creditduplicatesimage_url— no author, no licence, which is what actually matters for Wikimedia reuse.get_species.photoAttributiondoes this correctly ("(c) CIAT, some rights reserved (CC BY-SA)"), so the right shape already exists in-suite.explain_itemcategory facts rarely populate.Quartzwithcategory=mineralreturns "Wikidata returned no mineral facts for 'Quartz' (looked for: Mohs hardness)"; the Wikidata entity for quartz carries Mohs hardness 7. Only 1 of 5 calls returned any fact.9fbdb4eclaims to resolve entity facts to labels; the resolution still misses.get_milestonesreports eight different "current" culture values (27.71 … 910.32) for one world total, because Eco freezes each figure at completion.d504868reconciled the 0-vs-910 discrepancy well; this second discrepancy has no note.get_civicscannot identify what was elected.recentElections,recentOutcomesandrecentSettlementsreturnsubject: nullwith onlysubjectId, andproposerId: nullwhileproposerresolves to a name.Presentation
Eco colour markup leaks into names and keys.
find_tradestore labels and — more seriously —storeKeyvalues embed<color=red>…</color>.get_mapdeed names likewise. A key carrying markup is load-bearing and fragile.Float noise surfaced raw. Prices as
0.100000000692029and0.9100000063749999, costs as22.483333352864243,timeCost: 0.020000000000000004. Currency values want rounding at the presentation edge.get_governmentlaw previews are mangled. Raw\r\nsurvives, andpreview_linescontains"Wet Tailingsif Dropped"(missing separator) and"16 Tools16 Tools"(duplicated run).get_recipesstation filter rejects its own documented example. The schema says "Accepts the id or the display name, e.g. AnvilItem or 'Anvil'".station="Anvil"returns "no station named 'Anvil' exists in this recipe graph… Did you mean: AnvilObject?" Display-name resolution works forproductandskillbut notstation, and the id in the doc (AnvilItem) is also wrong — it isAnvilObject. Either fix the resolver or fix the docstring.get_currencycontradicts itself in every payload.holders_reachable: truesits besideholders_unavailable_note: "…it is not reachable right now", while individual currencies carryholders.reachable: false.get_currencynot-found suggestions are unactionable. A miss returnssuggestionscontaining raw numeric currency ids ("2533707","2967954"), not names.get_socialreputation graph is dominated by one unflagged actor.topReputationGiversleads with 2,788 against 115 for the next — round-number grants (204 / 136 / 68) to 26 distinct targets, consistent with a system or admin actor. It shapes the "Most-repped" headline with no outlier flag.get_marketomits the reconciliation note its siblings carry.get_trades.counts.noteandget_economy.trades_total_noteboth explain that 3,680 exporter rows = 528 detail + 3,152 rollups covering 22,405 merged = 22,933 events, and that/infocounts a different population again.get_marketreportstotalTrades: 22933with no such note, and its empty-filter warning cites a fourth number ("528 ledger rows").Verified correct — do not regress
Arithmetic and cross-tool consistency I checked independently, all of which passed:
CookingUtensils= 2 × IronBar @ 0.90 (market) + 50 cal × 0.001 + 0.4 min × 0.05 = 1.87 exactly; the 0.90 matchesget_market's IronBar median.SteelAxe: 20 × 0.7125 + 8 × 0.80 + 5 × 0.366667 = 22.4833 exactly.trade_watchersIronBartotalVolume548.520016671 ==get_trades.byItemIronBarItem 548.520016671 (exact).get_marketvolume 638 @ 0.10 ==get_trades.byItem63.8 currency.get_speciesBisonpopulationLatest118 ==get_regionBisonSpecies.current118.get_government.active_laws_count5 ==/infolaws5.get_map.worldDim1000×1000 ==/info"1km²";deedCount67 +seamCopyCount1 ==polygonCount68.get_civicsturnout 90 / (90 + 218) = 0.2922;netDistinctCitizens69 − 16 = 53.get_climate(427.4 − 400) / 25 = 1.1 ==peak_drives_candpeak_drives_m.get_region.speciesRiskcounts: 9 at_risk + 1 declining + 1 recovering + 3 growing + 80 stable = 94 ==speciesSeen.trade_watchersfull lifecycle: fuzzy match ("Iron Bar" →IronBarItem), threshold filtering correct (1 of 5 trades under 0.85),advance=falsehonoured, create-validation rejects a price watcher with no operator, removal works, bogus id returnsremoved: falserather than erroring.Fixture hygiene
trade_watcherswas the only write path exercised. The store was empty beforehand; two watchers were created, evaluated withadvance=falseso no watcher state advanced, then removed, andaction=listconfirmed empty afterwards. No residue.