get_economy reports a funded treasury as 0 because an unparseable body is read as an empty series #283

Closed
opened 2026-08-13 22:36:46 +00:00 by coilyco-ops · 1 comment
Member

Slice of #266, filed so PR #279 can close something it actually closes. Angie (ENG, claude seat).

266 is an invariant across 25 tools. This is one confirmed violation of it, already built.

The defect

get_economy   govt_funds: 0,  datasets_unavailable: [],  health: "healthy"
get_currency  money.governmentHoldings: 87912.99

Same dataset, same server, same minute. wages_total, taxes_paid, govt_funds_received and net_tax_flow are 0 too, and the health verdict and narrative are derived from them.

Cause

Everything downstream was already correct. _opt_last returns None for an absent series and 0.0 for one read and empty; fetch_economy files a name under datasets_unavailable only when _fetch_dataset returns None.

_fetch_dataset never returned None for a body it could not read. It returns a list — possibly empty — for any 200, so a dict under neither Values nor Points, rows keyed differently, or a non-list non-dict payload all yield zero parsed points, and an empty list is indistinguishable from a genuinely idle dataset.

Acceptance

  • A 200 whose body offers rows but parses to none reports the dataset as unreadable, so it lands in datasets_unavailable and its KPIs are null.
  • A genuinely empty series still reports [] and 0.0. Nothing happened and nothing was read stay distinct.
  • Rows that all fail to parse are unmeasured, not zero.
  • Each fails under a mutation restoring the old behaviour.

Why it is filed separately

AGENTS.md: "If a pull request does not fully close the issue that motivated it, file the slice as its own issue and close that one. Do not weaken the reference to satisfy the verb."

I wrote 279's body as refs #266 because it does not close the 25-tool sweep, and then did not file this — which left the pull request unmergeable rather than merely unclaimed. Correcting that.

**Slice of https://forgejo.coilysiren.me/coilyco-gaming/eco-app/issues/266, filed so PR https://forgejo.coilysiren.me/coilyco-gaming/eco-app/pulls/279 can close something it actually closes.** Angie (ENG, `claude` seat). 266 is an invariant across 25 tools. This is one confirmed violation of it, already built. ## The defect ``` get_economy govt_funds: 0, datasets_unavailable: [], health: "healthy" get_currency money.governmentHoldings: 87912.99 ``` Same dataset, same server, same minute. `wages_total`, `taxes_paid`, `govt_funds_received` and `net_tax_flow` are 0 too, and the health verdict and narrative are derived from them. ## Cause Everything downstream was already correct. `_opt_last` returns `None` for an absent series and `0.0` for one read and empty; `fetch_economy` files a name under `datasets_unavailable` only when `_fetch_dataset` returns `None`. `_fetch_dataset` never returned `None` for a body it could not read. It returns a list — possibly empty — for any 200, so a dict under neither `Values` nor `Points`, rows keyed differently, or a non-list non-dict payload all yield zero parsed points, and an empty list is indistinguishable from a genuinely idle dataset. ## Acceptance - A 200 whose body offers rows but parses to none reports the dataset as unreadable, so it lands in `datasets_unavailable` and its KPIs are `null`. - A genuinely empty series still reports `[]` and `0.0`. Nothing happened and nothing was read stay distinct. - Rows that all fail to parse are unmeasured, not zero. - Each fails under a mutation restoring the old behaviour. ## Why it is filed separately `AGENTS.md`: *"If a pull request does not fully close the issue that motivated it, file the slice as its own issue and close that one. Do not weaken the reference to satisfy the verb."* I wrote 279's body as `refs #266` because it does not close the 25-tool sweep, and then did not file this — which left the pull request unmergeable rather than merely unclaimed. Correcting that.
Author
Member

Reproduced live against the deployed service, minutes ago, read-only. And it narrows what the fix does. Angie (ENG, claude seat).

I had been arguing this from source. Here it is from the running service.

get_economy(eco.coilysiren.me:3001)
  govt_funds:              0
  datasets_unavailable:    []
  health:                  "healthy"
  narrative:               "Economy is healthy — no loans resolved, no contract activity recorded"
  wages_total / taxes_paid / govt_funds_received / net_tax_flow:  all 0

get_currency(eco.coilysiren.me:3001)     fetched_at_iso 2026-08-13T22:45:12Z
  money.governmentHoldings:  87,775.59

Same server, same minute, two answers. The verdict "Economy is healthy" is derived from the five zeros.

The part that sharpens the diagnosis

get_currency does not merely report a number — it returns the whole series, 42 points, rising from 0 through 28,081 to 87,775.59. And the dataset is listed as available:

available_currency_datasets: [..., "GovernmentHoldingsInDefaultCurrency", ...]

So the dataset is readable. get_currency reads it fine. get_economy asks for the same name through _fetch_dataset and gets nothing it can parse.

What that means for PR 279, stated honestly

279 makes the failure visible — the dataset lands in datasets_unavailable, govt_funds becomes null, and the KPIs built on it stop asserting zero. That is exactly what #266's rule 1 asks for, and it is the whole of this issue's acceptance.

It does not make govt_funds correct. After 279 the tool says "I could not read this" instead of "it is zero", which is the honest answer and not the useful one. Getting the number right means finding why _fetch_dataset cannot parse a series get_currency parses — a different request path, different params, or a different response shape.

I am flagging that rather than letting 279 look like it fixes the treasury figure. A null is a correct answer to a question this tool currently gets wrong; a number would be a better one, and that is a separate piece of work.

One thing that is working

The deployed service already bounds get_currency and says so:

"currencies: showing 3 of 185 rows; pass limit=0 for all of them
 (the summary fields above already cover every row)"
"personal: showing 3 of 183 rows; ..."

That is #267's rule 2 behaving correctly on the top-level arrays, which matches what I found in source. The holder cap I could not observe at all: holders.reachable is false on every currency because the stores exporter mod is not answering, so accountsCounted is 0 and the 15-row cap has nothing to cap.

**Reproduced live against the deployed service, minutes ago, read-only. And it narrows what the fix does. Angie (ENG, `claude` seat).** I had been arguing this from source. Here it is from the running service. ``` get_economy(eco.coilysiren.me:3001) govt_funds: 0 datasets_unavailable: [] health: "healthy" narrative: "Economy is healthy — no loans resolved, no contract activity recorded" wages_total / taxes_paid / govt_funds_received / net_tax_flow: all 0 get_currency(eco.coilysiren.me:3001) fetched_at_iso 2026-08-13T22:45:12Z money.governmentHoldings: 87,775.59 ``` Same server, same minute, two answers. The verdict *"Economy is healthy"* is derived from the five zeros. ## The part that sharpens the diagnosis `get_currency` does not merely report a number — it returns the **whole series**, 42 points, rising from 0 through 28,081 to 87,775.59. And the dataset is listed as available: ``` available_currency_datasets: [..., "GovernmentHoldingsInDefaultCurrency", ...] ``` **So the dataset is readable.** `get_currency` reads it fine. `get_economy` asks for the same name through `_fetch_dataset` and gets nothing it can parse. ## What that means for PR 279, stated honestly 279 makes the failure **visible** — the dataset lands in `datasets_unavailable`, `govt_funds` becomes `null`, and the KPIs built on it stop asserting zero. That is exactly what https://forgejo.coilysiren.me/coilyco-gaming/eco-app/issues/266's rule 1 asks for, and it is the whole of this issue's acceptance. **It does not make `govt_funds` correct.** After 279 the tool says "I could not read this" instead of "it is zero", which is the honest answer and not the useful one. Getting the number right means finding why `_fetch_dataset` cannot parse a series `get_currency` parses — a different request path, different params, or a different response shape. I am flagging that rather than letting 279 look like it fixes the treasury figure. **A null is a correct answer to a question this tool currently gets wrong; a number would be a better one**, and that is a separate piece of work. ## One thing that is working The deployed service already bounds `get_currency` and says so: ``` "currencies: showing 3 of 185 rows; pass limit=0 for all of them (the summary fields above already cover every row)" "personal: showing 3 of 183 rows; ..." ``` That is https://forgejo.coilysiren.me/coilyco-gaming/eco-app/issues/267's rule 2 behaving correctly on the top-level arrays, which matches what I found in source. The holder cap I could not observe at all: `holders.reachable` is false on every currency because the stores exporter mod is not answering, so `accountsCounted` is 0 and the 15-row cap has nothing to cap.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/eco-app#283
No description provided.