CN 区域构建下 src/main/usage 8 个计价测试必失败:断言与 #1302 的「兜底恒为 USD」设计冲突,卡死 CN 开发机提交门禁
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 401
- Avg merge
- 21h 40m
- Merged PRs (30d)
- 805
Description
cc @dashhuang(#1302 作者)——bug 根源涉及该 PR 的设计意图确认,详见「建议修法」。
## 一句话结论
#1302 把「账本币种兜底」的行为改成了**恒为 USD、绝不按构建区域猜**,但有 8 个测试的断言还停留在旧世界观「兜底 = 构建区域默认币种」。两者只有在 global 构建(默认币种恰好是 USD)下碰巧相等——所以 CI 永远是绿的,而任何 CN 区域配置的机器上 `pnpm test:unit` 必红。
## 原因(两边各自怎么说)
**源码这边**(`apps/desktop/src/main/usage/ledgerCurrency.ts`,#1302 引入):回退链是 `active → lastKnown → USD`,文件头注释明确写着设计理由——
> 最终兜底取 USD 而不是构建区域币种……兜底成 CNY 会把 USD 数值原样盖上 CNY 戳,产生 6.7 倍量级的错账。宁可显示得保守,不可记错。
> 不要改成 DEFAULT_USAGE_CURRENCY,**那正是本次修复要消灭的「按区域猜」**。
**测试这边**(`turnCostCalculator.test.ts` 「lets the build default ledger currency decide the SDK fallback」一例,注释原文):
> 没有活动账本币种(冷启动)时**由构建默认币种定夺**,断言因此跟着构建区域走……**不能写死 USD** —— 那样只有 Global 构建下能过。
两段注释针锋相对:测试作者为了「别只在 Global 下能过」特意写了区域条件断言,结果源码改成了区域无关的 USD 兜底,这批断言反而变成了「只有 Global 下能过」——恰好掉进了它自己想避免的坑。
受影响断言共 8 处:
- `src/main/usage/__tests__/modelPricing.test.ts` ×1(「restores the active ledger currency when only the disk cache is hydrated」:reset 后期望 `DEFAULT_USAGE_CURRENCY`,实际恒为 USD)
- `src/main/usage/__tests__/turnCostCalculator.test.ts` ×1(CNY 构建下期望 sdk-fallback 拒记返回 null,实际按 USD 兜底记了账)
- `src/main/usage/__tests__/usageHistory.test.ts` ×6(totals / modelDaily / anomaly / 缓存回放等,全是「期望 CNY 口径、实际 USD 口径」的派生)
## 为什么 CI 一直看不见
区域由构建期变量 `VITE_CINDY_AUTH_REGION` 决定,**没配置时默认 global**。CI 没配 → global → `DEFAULT_USAGE_CURRENCY = 'USD'` → 断言期望值和 USD 兜底碰巧相等 → 绿。只有在 `apps/desktop/.env` 里写了 `VITE_CINDY_AUTH_REGION=cn` 的开发机才会现形。
## 影响
1. **CN 区域开发机的提交门禁被卡死**:仓规要求提交前 `pnpm test:unit` 全绿,这 8 个红让 CN 配置的机器上**任何人提交任何改动都过不了门禁**(2026-08-03 一个纯文档 PR 实测被卡)。做中国大陆版的同学日常环境大概率就是 cn。
2. **CN 构建的计价行为实际上是零测试覆盖**:这 8 个断言本来是专门盯 CNY 账本分支的,现在它们在 CI 上跑的永远是 USD 分支——将来若有人真把 CN 构建的记账逻辑改坏,CI 同样看不见。
3. **不是产品事故**:线上行为是 #1302 刻意设计的那个(兜底 USD),用户侧没有错账。坏的是测试,不是功能。
## 建议修法
前提先确认:**以哪边的意图为准**。若 #1302 的「兜底恒为 USD」是终局设计(源码注释的论证看起来是),修法即:
1. 把 8 处断言改成区域无关的 USD 期望,删掉 `DEFAULT_USAGE_CURRENCY === 'USD' ? … : …` 条件;
2. 建议给 CI 加一条 cn 区域测试腿(`VITE_CINDY_AUTH_REGION=cn` 至少跑一次 `src/main/usage` 目录),否则这类「global 碰巧对」的潜伏 bug 还会再来。
若测试注释代表的产品意图才是对的(CNY 构建冷启动就该拒记 USD sdk-fallback),那要改的就是源码回退链,请 #1302 作者裁决。
## 复现
```bash
# 任何机器,无需 .env:
VITE_CINDY_AUTH_REGION=cn pnpm --dir apps/desktop exec vitest run \
src/main/usage/__tests__/modelPricing.test.ts \
src/main/usage/__tests__/turnCostCalculator.test.ts \
src/main/usage/__tests__/usageHistory.test.ts
# → 8 failed | 57 passed;把 cn 换成 global → 65 全过
# 已验证:干净 origin/main(439de1658)可复现,与工作区改动无关
```
Contributor guide
Research direction
Confirm the intended fallback behavior in apps/desktop/src/main/usage/ledgerCurrency.ts and compare it with the affected assertions in modelPricing.test.ts, turnCostCalculator.test.ts, and usageHistory.test.ts. Run the provided VITE_CINDY_AUTH_REGION=cn Vitest command first. Done means all 65 tests pass under both cn and global configurations, with expectations matching the confirmed design.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100