Economic Health Dashboard #12

Closed
opened 2026-06-17 07:29:11 +00:00 by coilysiren · 2 comments
Owner

Originally filed by @coilysiren on 2026-05-02T23:09:36Z

Task 2 — Economic Health Dashboard

Prereq: read todo/README.md first for cross-cutting conventions (SSM region, template paths, iframe CSP, Day-3 data thinness).

Goal

Build an MCP tool get_eco_economy that renders an iframe card showing a live economic vitals board for the Eco server.

Data sources

All from /datasets/get?dataset={Name}&dayStart=0&dayEnd={days_elapsed} on http://eco.coilysiren.me:3001. Admin endpoint — requires X-API-Key header from SSM /eco-mcp-app/api-admin-token (region us-east-1).

Verified-present stat names (all 14 confirmed in /datasets/flatlist on live server):

  • OfferedLoanOrBond, AcceptedLoanOrBond, RepaidLoanOrBond, DefaultedOnLoanOrBond
  • PayWages, PayRentOrMoveInFee
  • PostedContract, CompletedContract, FailedContract
  • PropertyTransfer, ReputationTransfer, TransferMoney
  • PayTax, ReceiveGovernmentFunds

Also pull from GET /info (public):

  • EconomyDesc (string like "524 trades, 0 contracts")
  • TotalCulture (number; this is a /info field, NOT a /datasets stat/datasets/get?dataset=TotalCulture returns 500)

Compute days_elapsed from /info's TimeSinceStart (seconds) → days.

Card layout (iframe at /mcp/ui/economy)

  • Top KPI row: trades/day, contract completion ratio, loan default rate, total wages paid, net tax flow
  • Middle: 3–4 sparklines of the most volatile series (pick by stddev of the normalized time series)
  • Narrative strip: "Economy is {healthy|stressed|booming} — {N}% default rate, {M}% contracts completed"

Classification thresholds (seed values, tune as you watch real data):

  • booming: trades/day up 20% week-over-week AND default rate < 5%
  • stressed: default rate > 15% OR contract failure rate > 30%
  • healthy: otherwise

Implementation notes

  • Chart.js inlined (not CDN at runtime — CSP). Copy pattern from existing template.
  • Follow existing iframe/partial pattern in src/eco_mcp_app/templates/ (note: templates/, not ui/).
  • Add MCP tool in src/eco_mcp_app/server.py.
  • Cache the dataset fetches for 30–60 seconds in-process — the dashboard will be viewed in bursts.

Out of scope

  • Pollution metrics — nerfed in current cycle, don't wire them.

Acceptance

  • Card renders with live numbers at inv harness.
  • Fresh/zero-data paths render without JS errors (Day-3 reality: most series will have only a handful of data points).
  • inv smoke passes with the new tool registered.
  • Unit tests with respx mocking the admin endpoints for at least the KPI computation.

Migrated from coilyco-flight-deck/eco-mcp-app#14 during the eco repo consolidation (coilysiren/inbox#100).

_Originally filed by @coilysiren on 2026-05-02T23:09:36Z_ # Task 2 — Economic Health Dashboard **Prereq**: read `todo/README.md` first for cross-cutting conventions (SSM region, template paths, iframe CSP, Day-3 data thinness). ## Goal Build an MCP tool `get_eco_economy` that renders an iframe card showing a live economic vitals board for the Eco server. ## Data sources All from `/datasets/get?dataset={Name}&dayStart=0&dayEnd={days_elapsed}` on `http://eco.coilysiren.me:3001`. **Admin endpoint** — requires `X-API-Key` header from SSM `/eco-mcp-app/api-admin-token` (region `us-east-1`). Verified-present stat names (all 14 confirmed in `/datasets/flatlist` on live server): - `OfferedLoanOrBond`, `AcceptedLoanOrBond`, `RepaidLoanOrBond`, `DefaultedOnLoanOrBond` - `PayWages`, `PayRentOrMoveInFee` - `PostedContract`, `CompletedContract`, `FailedContract` - `PropertyTransfer`, `ReputationTransfer`, `TransferMoney` - `PayTax`, `ReceiveGovernmentFunds` Also pull from `GET /info` (public): - `EconomyDesc` (string like `"524 trades, 0 contracts"`) - `TotalCulture` (number; **this is a /info field, NOT a /datasets stat** — `/datasets/get?dataset=TotalCulture` returns 500) Compute `days_elapsed` from `/info`'s `TimeSinceStart` (seconds) → days. ## Card layout (iframe at `/mcp/ui/economy`) - **Top KPI row**: trades/day, contract completion ratio, loan default rate, total wages paid, net tax flow - **Middle**: 3–4 sparklines of the most volatile series (pick by stddev of the normalized time series) - **Narrative strip**: `"Economy is {healthy|stressed|booming} — {N}% default rate, {M}% contracts completed"` Classification thresholds (seed values, tune as you watch real data): - `booming`: trades/day up 20% week-over-week AND default rate < 5% - `stressed`: default rate > 15% OR contract failure rate > 30% - `healthy`: otherwise ## Implementation notes - Chart.js inlined (not CDN at runtime — CSP). Copy pattern from existing template. - Follow existing iframe/partial pattern in `src/eco_mcp_app/templates/` (note: `templates/`, not `ui/`). - Add MCP tool in `src/eco_mcp_app/server.py`. - Cache the dataset fetches for 30–60 seconds in-process — the dashboard will be viewed in bursts. ## Out of scope - Pollution metrics — nerfed in current cycle, don't wire them. ## Acceptance - Card renders with live numbers at `inv harness`. - Fresh/zero-data paths render without JS errors (Day-3 reality: most series will have only a handful of data points). - `inv smoke` passes with the new tool registered. - Unit tests with `respx` mocking the admin endpoints for at least the KPI computation. --- _Migrated from coilyco-flight-deck/eco-mcp-app#14 during the eco repo consolidation (coilysiren/inbox#100)._
coilysiren added
P3
and removed
P2
labels 2026-06-17 08:39:07 +00:00
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-eco-app-12 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-05T04:32:29Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

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 agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-eco-app-12` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-05T04:32:29Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **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). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - fixed the tautological week-over-week calc so the booming economy classification is actually reachable, landed on main.

The surprise here was that the feature was already fully built and merged via the big eco-app consolidation commit — issue-12 started life identical to main, tests green, tool registered, card rendering. So this wasn't a build-from-scratch; it was reading a finished implementation closely enough to find the one real crack.

That crack: the WoW trades delta derived the trailing-7-day rate from the cumulative average, which is algebraically that same average — so trades_wow_pct was always exactly +0.0%, the card printed a meaningless "+0.0% vs avg", and the booming branch was dead code that could never fire. Replaced it with a genuine trailing-7 vs prior-7 in-game-day window summed across the datasets as an activity proxy (Eco only exposes trade count as a scalar, never a series, so a literal trades/day WoW is genuinely uncomputable). Added tests proving booming now triggers, that WoW stays None before two weeks, and that stressed still wins over booming.

Fairly confident — 399 tests pass, lint/mypy/precommit clean, and I rendered a synthetic booming card end-to-end to confirm the new label. Honest rough edge: 'total economic activity' is a proxy, not real trade velocity, and the thresholds are still the spec's untuned seed values. Worth a follow-up to watch real Day-14+ data and tune, and maybe to have the replay/telemetry mod emit a proper per-day trades series so the WoW can key off the real thing instead of a proxy.

WARD-OUTCOME: done - fixed the tautological week-over-week calc so the `booming` economy classification is actually reachable, landed on main. The surprise here was that the feature was *already* fully built and merged via the big eco-app consolidation commit — `issue-12` started life identical to `main`, tests green, tool registered, card rendering. So this wasn't a build-from-scratch; it was reading a finished implementation closely enough to find the one real crack. That crack: the WoW trades delta derived the trailing-7-day rate from the cumulative average, which is algebraically that same average — so `trades_wow_pct` was always exactly +0.0%, the card printed a meaningless "+0.0% vs avg", and the `booming` branch was dead code that could never fire. Replaced it with a genuine trailing-7 vs prior-7 in-game-day window summed across the datasets as an activity proxy (Eco only exposes trade *count* as a scalar, never a series, so a literal trades/day WoW is genuinely uncomputable). Added tests proving booming now triggers, that WoW stays None before two weeks, and that stressed still wins over booming. Fairly confident — 399 tests pass, lint/mypy/precommit clean, and I rendered a synthetic booming card end-to-end to confirm the new label. Honest rough edge: 'total economic activity' is a proxy, not real trade velocity, and the thresholds are still the spec's untuned seed values. Worth a follow-up to watch real Day-14+ data and tune, and maybe to have the replay/telemetry mod emit a proper per-day trades series so the WoW can key off the real thing instead of a proxy.
Sign in to join this conversation.
No description provided.