Files
DeepSeek-Reasonix/docs/superpowers
SivanCola ee17c62901 Unify multi-currency billing across all surfaces / 统一全链路计费与币种 (#8058)
* feat(billing): unify multi-currency cost accounting

Problem:
Reasonix exposed provider prices, wallet balances, and session totals through independent currency paths. Mixed model runs could clear or mislabel costs, and display preferences could mutate regional list prices.

Root cause:
The runtime had no currency-tagged money domain, occurrence-time valuation, or shared quote boundary. Individual sinks accumulated floating-point Pricing.Cost values and inferred display semantics locally.

Fix:
Introduce fixed-point Money, CostQuote, official regional price catalogs, ECB FX snapshots, occurrence-time ledgers, wallet conversion, config v6 migration, and a central quote sink shared by Desktop, Serve, CLI, ACP, Remote, stats, and eventwire. Preserve additive legacy aliases and document the new contracts in English and Chinese.

Verification:
- go test ./...
- (cd desktop && go test ./...)
- (cd desktop/frontend && pnpm typecheck && pnpm test:usage-stats && pnpm build)
- go test -race ./internal/billing ./internal/event ./internal/stats ./internal/boot ./internal/config ./internal/cli ./internal/acp ./internal/serve
- go test -race ./internal/billing ./internal/acp ./internal/eventwire ./internal/event
- golangci-lint run --timeout=5m
- (cd desktop && golangci-lint run --timeout=5m)
- go run ./tools/repolint
- ./scripts/cache-guard.sh
- CACHE_IMPACT_PR_BODY_FILE=/tmp/reasonix-billing-pr-body.md ./scripts/check-cache-impact.sh
- DOCS_IMPACT_PR_BODY_FILE=/tmp/reasonix-billing-pr-body.md ./scripts/check-docs-impact.sh
- git diff --check

* fix(billing): keep cost totals complete and lossless

Problem:
Exact original-currency totals could be marked incomplete when an unused FX valuation was unavailable. CLI and ACP recomputed authoritative totals from a 64-quote sample, and live controllers retained the pre-refresh FX table pointer.

Root cause:
CostQuote completeness conflated cost-fact availability with optional valuation coverage. Run surfaces used bounded quote slices as ledgers, while QuoteContext captured a one-time RateTable snapshot.

Fix:
Make completeness follow the selected shared display total, preserve unrecoverable fact failures, and keep incomplete frontend quotes unavailable. Accumulate CLI and ACP totals through the billing ledger, including restored ACP scalar history, and read the current FXCache snapshot for every quote.

Verification:
- go test ./...
- go test -race ./internal/billing ./internal/event ./internal/boot ./internal/cli ./internal/acp
- (cd desktop && go test ./... && go vet ./...)
- pnpm --dir desktop/frontend typecheck
- pnpm --dir desktop/frontend build
- ./scripts/cache-guard.sh
- go run ./tools/repolint

* refactor: remove runtime FX from billing

Problem: runtime FX downloads and wallet conversion mixed pricing estimates with provider balances and could fabricate cross-currency totals.

Root cause: CostQuote, ledger aggregation, display selection, and wallet rendering shared one currency path and treated display completeness as cost completeness.

Fix: keep fixed-point original facts, restrict new valuations to identity and official regional tables, add explicit cost/display status and currency buckets, remove ECB startup/cache paths, and use exact original wallet balances with runtime-only hints.

Verification: go test ./..., desktop go test ./..., targeted race suites, frontend typecheck/usage-stats/build, cache guard, cache-impact review, and secret scan.

* Fix display-only currency rebinding

Problem: changing the billing display currency still rebuilt Desktop controllers, stale wallet responses could bind a newer session, and two obsolete locale-pricing helpers failed golangci-lint.

Root cause: the display preference reused the general runtime-settings rebuild path, while wallet callbacks validated only the controller pointer and had no tab/session display generation.

Fix: persist the preference without rebuilding, re-select existing ledger valuations across runtime tabs, compare-and-apply wallet hints against controller and telemetry generation, and remove the obsolete locale-pricing paths.

Verification: focused RED/GREEN tests; Desktop focused race tests; go test ./... in root and desktop; go vet; golangci-lint; repolint; cache-impact check.

* Clarify cost display currency settings

Problem: the Desktop setting still used ambiguous pricing terminology and packed the auto-selection rule into the segmented control.

Root cause: the billing refactor renamed the preference but left the surrounding appearance copy and compact option label partially aligned with the old pricing semantics.

Fix: present one cost-display preference, mark auto as recommended, explain wallet, pricing-table, fallback, and mixed-currency behavior in the hint, and align English, Simplified Chinese, and Traditional Chinese copy.

Verification: source contract scan; pnpm typecheck; pnpm build with bundle budgets.

* Shorten cost display currency guidance

Problem: the Desktop cost-display hint wrapped to roughly four lines and visually dominated the setting row.

Root cause: fallback and mixed-currency details duplicated behavior already surfaced by the cost UI.

Fix: retain only the display-only contract and automatic currency-selection order in concise English, Simplified Chinese, and Traditional Chinese copy.

Verification: in-app browser DOM measurement at 904x936; pnpm typecheck; pnpm build with bundle budgets.

* Fix narrow settings control overflow

Problem:
- General settings kept its two-column layout at narrow desktop widths, clipping controls at the modal edge.

Root cause:
- A component-specific 900px override won over the shared 980px responsive rule and sized the row independently of its actual content pane.

Fix:
- Make the general page an inline-size container and stack fields below 620px of available width.
- Align the media-query fallback with the shared 980px breakpoint.
- Add responsive and startup contract coverage.

Verification:
- pnpm test:settings-responsive
- pnpm exec tsx src/__tests__/startup-settings-contract.test.ts
- pnpm check:css
- pnpm typecheck
- pnpm build
- 904x936 browser DOM check: maximum control overflow is 0px
2026-08-11 19:02:51 +08:00
..