fix(chart): keep account and chart-view birth truth consistent

This commit is contained in:
jesse-ux
2026-09-22 12:14:50 +08:00
parent dd4141a030
commit cc7ef8a339
21 changed files with 1243 additions and 90 deletions
+16
View File
@@ -13200,6 +13200,22 @@
- 复发自:无
- 修复版本:`2503c019`
## BUG-996 | 更新出生资料后星盘仍可能显示旧盘或无法区分失败原因
- 状态:resolved
- 首次发现:2026-09-22
- 最近更新:2026-09-22
- 影响面:`PATCH /api/account``GET /api/account``GET /api/chart-view``frontend/src/lib/secondary-page-data.ts` 的星盘快照缓存
- 用户现象:已经更新出生时间,打开星盘仍像没有可显示内容,或点开后看不到刚保存的日期和时间。现场这一户的数据库行没有取到,不能把某一种残缺资料写成已经证实的唯一原因。
- 触发条件:账户资料 PATCH 成功后星盘模块缓存仍留着上一张快照;或 `profiles` 读取失败、已采用日期缺 offset、时区解析失败、引擎 429 / 超时 / 坏结果被收成同一种「资料不完整」或同一句失败。
- 根因:三处代码断点同时存在,不是一条已经证实的现场数据。第一,chart-view 忽略 profile 查询错误,空行会落到 `birth_profile_incomplete`;已采用日期缺 offset 或时区解析抛错时没有稳定分类。第二,`chartCache` 不按账户和资料指纹换键,PATCH 成功后也不丢弃旧快照。第三,账户响应和星盘排盘各自读日期、时间、offset,确认后的普通编辑虽不覆盖 active time,但调用方看不到同一份服务端真值。`guard_adopted_birth_date` 会把 adopted date、offset、provenance 一起清空,不会留下「有日期、没 offset」的半截元组,因此本轮不加迁移。
- 修复:账户 PATCH / GET 与 chart-view 共用 `resolveServerOwnedChartBirth`。chart-view 把查询失败、资料不完整、adopted 计算不完整、时区失败、引擎忙、超时、坏结果和响应格式失败分开,查询失败不再写成资料不完整。PATCH 成功后按账户和资料指纹钉住星盘缓存,进行中的旧请求不能把旧盘写回去。确认状态的普通编辑仍不覆盖 active time。不把 `chart_profiles` 当作 `/chart` 真值,不放宽 accepted / confirmed。
- 验证:`frontend/tests/chart-profile-update-consistency.test.ts` 覆盖 reported、accepted、confirmed、跨午夜、缺 active offset、查询失败、时区失败、引擎分档、schema 失败、旧快照失效和 D1。旧行为下查询错误没有独立 reason、缓存也没有账户指纹键,这些断言不会过。现场单户数据库状态仍未取证。
- 防复发:数据库查询错误不得映射成 `birth_profile_incomplete`。已采用日期存在而 offset 缺失时不得回退到声明 offset 或清空 `active_birth_time`。星盘快照键必须包含账户和资料指纹;引擎缓存键仍包含日期、时间、offset、ayanamsa、node mode。失败文案不得写「过一会儿再打开」或没有上下文的「没有可显示内容」。
- 相关记录:BUG-073、BUG-076、BUG-715、BUG-716、BUG-717、TASK-chart-profile-update-consistency-20260922
- 复发自:无。BUG-073 仍要求服务端不信任客户端咨询模式;BUG-076 仍要求 `profiles` 而不是星盘库 JSON 为真值;BUG-715 至 717 的星盘打开、分档日志和开页只打 `/api/chart` 都还在,本条补的是资料真值和快照失效。
- 修复版本:本分支,尚未推送、尚未部署
## BUG-997 | 切换人物后普通聊天仍用登录用户本人的出生资料
- 状态:resolved
@@ -0,0 +1,42 @@
# 进度 · 更新出生资料后星盘真值一致性(2026-09-22)
基线:`10baeb2fa865743c428806e115ac92ca9d92fb71``origin/staging`)。分支 `codex/chart-profile-update-consistency-20260922`。未推送,未部署。
## 做了什么
- `PATCH /api/account``GET /api/account``GET /api/chart-view` 共用 `resolveServerOwnedChartBirth`。reported 用声明日期、声明钟点和声明 offsetaccepted / confirmed 的完整 adopted 元组用 active date、active time、active offset 和 provenance;跨午夜同此。
- confirmed 的普通编辑仍返回空的 application patch,不覆盖 `active_birth_time`。声明字段变化时,与 `guard_adopted_birth_date` 相同:date、offset、provenance 一起清空,排盘落到既有的无 adopted 日期路径(声明日期 + 受保护的 active 分钟 + 声明 offset)。不是半截元组。
- accepted 的普通声明编辑仍把状态收成 reported 并清空 active timeadopted 元组一并清空,不会停在「还能排、但 offset 缺了」。
- adopted 日期在而 offset 缺失:`adopted_calculation_incomplete`,不回退声明 offset,也不去调时区解析。
- chart-view 分开记录:`profile_query_error``profile_incomplete``adopted_calculation_incomplete``timezone_resolver_failure``engine_busy``engine_timeout``engine_bad_payload``engine_http_error``response_schema_failure`。查询失败的 HTTP 仍是 200 结构化状态,但 status 不是 `birth_profile_incomplete`。日志只有 reason、route、耗时、HTTP status。
- 星盘模块缓存按账户 id + 资料指纹钉住。PATCH 成功立刻换键并丢掉不匹配的旧快照;与这次保存重叠的 `refreshAccount` 不会把旧指纹钉回去。进行中的旧 `/api/chart-view` 不能写回旧盘。引擎缓存键仍含日期、时间、offset、ayanamsa、node mode。
- `/chart` 仍读账户 `profiles`,不读 `chart_profiles`
## 没有新迁移
`20260920020000_adopted_birth_date.sql``guard_adopted_birth_date` 在同一分支把 `active_birth_date``active_birth_timezone_offset``active_birth_provenance` 置空,不会只清 offset。因此没有「可排盘且 adopted 元组不完整」的 trigger 产物,不加迁移,不跑 `npm run test:db`
## 断言变更
无。既有 `chart-view-route``chart-view-engine``server-owned-birth-profile``adopted-birth-date``account-api``secondary-page-entry` 的测试名和断言原值都没改。
## 测试
| 命令 | 结果 |
| --- | --- |
| `.\node_modules\.bin\tsc --noEmit` | 通过 |
| `npm run lint` | exit 00 error119 条既有 warning,本次改动的文件不在其中 |
| `npx tsx --test tests/chart-profile-update-consistency.test.ts` | 11 pass / 0 fail |
| 同命令加上 `chart-view-route``chart-view-engine``server-owned-birth-profile``adopted-birth-date``account-api``secondary-page-entry` | 57 pass / 0 fail |
未跑全量 `npm test`,未跑 `next build`
## 偏差
- 现场那一户的数据库行仍未知,BUG-996 不把某一种残缺写成唯一根因。见 `BLOCKED.md`
- 账户 GET 的 `chartBirth` 是库存真值。chart-view 只在声明 offset 缺失、且不是 adopted 半截元组时,才在内存里补时区;指纹仍用库存行,所以和 GET 的键一致。带齐 offset 的合成 fixture 上,日期、时间、offset、provenance 完全相同。
- 没有改 `frontend/src/app/(app)/page.tsx`、没有改 `scripts/jyotish_api_server.py`、没有改迁移。
## 环境缺口
无受控登录态,不能复核会议里的那一户。无新迁移,故不用 Docker 跑 `test:db`