Skip to content

fix(ui): restore the trades card on the operator overview - #176

Merged
argszero merged 1 commit into
mainfrom
fix/ops-trades-card
Sep 12, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/ops-trades-card

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Restore the trades card on the operator overview.

GET /api/ops/runtime has returned total_txs — a global COUNT(*) FROM transactions — since 85982e8 (PR #80, v0.3.3). The live operator view never rendered it. The mock branch did:

stat(T("ops.stats.trades"), T("cnt.trades", { n: txs.length }), T("ops.stats.trades.sub"))

and 89963f3 ("refactor(ui): zero mock data in logged-in views…", v1.22) deleted that line without re-pointing the live branch at rt.total_txs, which the same response object already carried.

So this is a regression being repaired, not a new feature. It is also not prototype parity: the prototype has four ops cards and no trades card (交易 occurs 0 times in docs/prototype/aitokenpool-console.html), while the live view has nine cards by design. Nothing is trimmed toward the prototype.

The card's two i18n keys (ops.stats.trades, ops.stats.trades.sub) already existed in both packs — that is why this change adds no keys, and the language-pack gate's key counts stay at 786/786.

Related Issue

No issue exists for this (found by a repo-wide orphan-key and unconsumed-response-field sweep). Filed up front instead.

Changes

  • ui/js/app.js: the live card list renders total_txs via the pre-existing keys, placed directly after the keys card — the position the mock branch had.
  • src/routes/mod.rs: new route test ops_runtime_total_txs_is_global_and_all_types.
  • src/i18n_pack.rs: the maintained call-site controls move 535 → 538 and 429 → 431 (3 new T() calls; cnt.trades was already distinct via the dashboard). Key counts deliberately unchanged at 786 / 786 — the tripwire that proves no key was added.
  • ui/index.html: cache-bust ?v=20260912-1 → ?v=20260912-2 (5 refs).
  • ui/README.md: documents the restored card and why it is not a prototype alignment.
  • No config/data-structure change, so config.example.toml needs no sync.

Tests

  • cargo test — 165 passed / 0 failed (164 + 1 new)
  • cargo fmt --check — clean
  • cargo clippy --all-targets -- -D warnings — 0 warnings
  • New unit test added (see below)

Why the field had no test, and why that mattered: grep total_txs src/routes/ops.rs found it only at the compute line and the serialize line — zero assertions in either direction. That absence is precisely why a load-bearing field could go unused for 23 commits. The new test pins both facts: that it is returned, and that its scope is the whole table across all types. The three rows it creates span two users (admin's topup via the real credits endpoint + demo's consume/earn), so the expected 3 differs from both a consume-only count (1) and a per-user max (2) — either degradation is falsifiable, and both are asserted as explicit counter-checks.

Teeth verified by injection: degrading the query to WHERE type = 'consume' reddens the new test with total_txs: 1 (expected 3); restored byte-identically afterwards (md5-verified).

A/B runtime proof (24/24): both legs generated from the real #ops-stats expression and the real fmtUptime, with the real pre-change source (git show HEAD:ui/js/app.js) as the before leg — not a perturbation of the after source. BEFORE 8 cards, no trades label; AFTER 9 cards, value rendered from the response (12345 → 12345 笔 / 12345), subtitle 累计全部类型 / all types, positioned right after the keys card. Changing total_txs to 777 moves the card, proving the value is not a constant; the mock row count (8) is asserted absent, keeping the zero-mock rule intact.

Checklist

  • Branch naming follows the convention (fix/)
  • Commit message uses Conventional Commits
  • Single responsibility, minimal change

`GET /api/ops/runtime` has returned `total_txs` (a global
`COUNT(*) FROM transactions`) since 85982e8 (PR #80), but the live
operator view never rendered it. The mock branch did:

    stat(T("ops.stats.trades"), T("cnt.trades", { n: txs.length }),
         T("ops.stats.trades.sub"))

and 89963f3 ("zero mock data in logged-in views", v1.22) deleted that
line without re-pointing the live branch at `rt.total_txs`, which the
same response object already carried. So this is a regression being
repaired, not a new feature — and not prototype parity: the prototype
has four ops cards and no trades card at all, while the live view has
nine by design.

The card's two i18n keys were already present in both packs, which is
why the change adds no keys.

The field had no assertion in either direction, which is exactly why it
could sit unused for 23 commits: `grep total_txs src/routes/ops.rs`
found only the compute and the serialize lines. The new route test
pins both that it is returned and that its scope is global and
all-types (rows span two users, so a per-user or consume-only
regression is falsifiable). No production backend change: the field
already ships.
@argszero
argszero merged commit 4830248 into main Sep 12, 2026
1 check passed
@argszero
argszero deleted the fix/ops-trades-card branch September 12, 2026 03:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant