Files
Jyotisha/docs/tasks/TASK-chart-profile-update-consistency-20260922.md
T
2026-09-22 11:19:35 +08:00

108 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 任务书 · 更新出生资料后星盘真值一致性与可诊断错误(2026-09-22)
## 0. 基线与串行关系
- 基线 commit:`1bc6a954c597e2817fe72bfedad93119ab19a527`(当前 `origin/staging`)。执行方开工前必须重新 `git fetch origin --prune`,再以最新 `origin/staging` 为基线。
- 执行分支:`codex/chart-profile-update-consistency-20260922`;工作树:`.worktrees/chart-profile-update-consistency-20260922`。
- 本单是星盘现场测试暴露的功能修复,不是整页重设计。与既有 `TASK-chart-page-blocking-open-20260915.md`、`TASK-chart-vedastro-decouple-20260915.md`、`TASK-readonly-pages-fix-20260916.md` 有交集时必须串行:先核对这些分支是否已合入 staging;未合入时不得同时改同一符号,按“既有星盘打开链路 → 本单资料真值一致性”顺序执行。
- 本单不接入 `chart_profiles` 作为 `/chart` 的主资料来源;`/chart` 继续使用账户权威 `profiles`。人物资料库属于普通聊天的另一条 subject binding 任务。
- 与既有星盘打开链路任务严格串行:先完成并核对 `TASK-chart-page-blocking-open-20260915.md`、`TASK-chart-vedastro-decouple-20260915.md`、`TASK-readonly-pages-fix-20260916.md` 的 staging 状态,再处理本单真值/缓存;不得并行修改相同 chart-view loader、engine client 或错误映射符号。
## 1. 事故实证
会议现场反馈:用户已经更新出生时间,但打开星盘仍提示没有可显示内容,或点击后无法打开。按产品设计,填写出生资料后应能生成并查看星盘。
调查已确认的代码事实(按符号定位,不依赖脆弱行号):
- `frontend/src/app/(app)/chart/page.tsx` 只挂载客户端 chart 壳;`frontend/src/hooks/use-chart-page.ts` 通过 `refreshChartPage()` 请求 `/api/chart-view`。
- `frontend/src/lib/chart-view-client.ts` 对响应做 JSON/Zod 合同解析;解析失败或请求失败会归并为通用 `chart_unavailable`。
- `frontend/src/lib/secondary-page-data.ts` 的 `chartCache` 是模块级单值缓存,没有账户/profile 版本键;资料 PATCH 成功后没有明确的 chart snapshot 失效边界。
- `frontend/src/lib/chart-view-service.ts` 从 `profiles` 读取 `ACCOUNT_BIRTH_SELECT`,再经 `server-owned-birth-profile.ts` 与 timezone resolver 组装排盘资料。
- accepted/confirmed 资料存在 `active_birth_date` 但缺 `active_birth_timezone_offset` 时,`server-owned-birth-profile` / `birth-profile-timezone` 会抛出 `adopted_birth_calculation_incomplete` 或 timezone error;当前错误路径可能最终只显示通用不可用状态。
- `frontend/src/lib/account-profile-patch.ts` 的普通账户 PATCH 主要处理 active time/status,不会在所有声明变化后原子维护 adopted date/offset/provenance;迁移 `frontend/supabase/migrations/20260920020000_adopted_birth_date.sql` 的 trigger 会在特定字段变化时清理 adopted tuple。这需要实证核对,不能在任务书外擅改出生资料语义。
- `loadChartView` 对 profile 查询错误的区分不足,数据库读取失败可能被误认为资料不完整。
相关历史:BUG-005、BUG-009、BUG-018、BUG-073、BUG-076、BUG-715~717、BUG-936。BUG-936 是首页 JS 死屏,不替代本单的 `/chart` 数据真值问题。
## 2. 根因
当前已确认的是“错误分类、资料更新一致性和客户端旧快照存在断点”;具体现场账号命中的单一数据库状态尚未证明。因此本单不得把某个假设写成已确认根因。优先验证并修复三层:
1. `/api/account` PATCH、数据库 trigger/adoption 与 `profiles` 中 date/time/offset/provenance 的原子一致性;
2. `GET /api/chart-view` 对 profile/query/timezone/engine/schema 各类失败的结构化分类;
3. profile 更新、account refresh、chart request 和 `chartCache` 之间的失效与竞态。
## 3. 决策记录(产品授权)
- 产品授权:填写出生资料后必须能够生成并查看星盘;不能用“资料还在,过一会儿再打开”掩盖永久错误。
- 保持现有安全语义:reported、accepted、confirmed、candidate、active provenance 不得混为一谈;confirmed 的普通资料编辑不得覆盖受保护的 active time。
- 失败要可理解、可诊断;不得把数据库错误、资料不完整、时区 adopted tuple 错误、引擎忙/超时和响应格式错误静默归成一个空状态。
- 本单不顺手改星盘算法、Dasha、校正算法、Node/Ayanamsa 业务规则,也不把 `chart_profiles` 作为 `/chart` 真值。
- 若现有迁移/trigger 与上述边界冲突,执行方必须停在任务书与 BUG 记录中,不能自行放宽或删除保护。
## 4. 硬红线
1. 不能信任客户端出生日期、时间、地点或 offset 覆盖服务端 profile 真值。
2. 不得通过清空 `active_birth_*`、放宽 accepted/confirmed 校验或 fallback 到不一致声明值来“修复”页面。
3. 不得把数据库 query error 当作 `birth_profile_incomplete`;日志不得记录姓名、出生日期/时间、坐标、完整请求体、Cookie、JWT、密钥或模型原文。
4. 不新增 spinner、骨架屏或第二套滚动/加载机制;继续遵守 `frontend/DESIGN.md` 与 `frontend/docs/VOICE.md`。
5. 不修改 `scripts/jyotish_api_server.py` 增长红线,不改 `.gitea/workflows/**`,不提升 `main`。
6. 若动表,必须通过向后兼容迁移并运行 `npm run test:db --prefix frontend`;删除/重命名/收紧约束必须另轮。
7. 任何既有断言变更都要写“原值 / 新值 / 原因”;测试名不得减少。
## 5. 任务分解与验收标准
### T1 · 端到端重放并锁定服务端真值
- 用 synthetic/golden fixture 覆盖 reported、accepted、confirmed、跨午夜 adopted date;不要写真实用户资料。
- 逐段核对 `PATCH /api/account → GET /api/account → GET /api/chart-view`,确认 status、reported time、active time、active date、timezone id/offset、provenance 的语义一致。
- 若发现 PATCH/trigger 清掉 adopted tuple 后仍留下可排盘的 active 状态,修复为原子、可解释的状态转换;confirmed 保护保持不变。
验收:同一 fixture 的 account 与 chart-view 返回相同的 server-owned date/time/offset;accepted/confirmed 不出现可排盘但 adopted tuple 不完整的状态;reported 仍按声明字段排盘;跨午夜使用 adopted date;confirmed 普通编辑仍不能覆盖 active time。
### T2 · 锁定 chart-view 错误分类
- 为 profile query error、profile incomplete、adopted calculation incomplete、timezone resolver failure、engine 429、engine timeout、bad payload、response schema failure 建立稳定内部分类和用户可读映射。
- 保留 HTTP/API 兼容性,除非测试证明现有状态码无法表达安全边界;不要把 200 的结构化业务状态随意改成异常 500。
- 日志只记稳定类别、route、耗时和必要的 HTTP status,不记出生资料。
验收:每类错误有独立测试;数据库读取失败不再伪装成 profile incomplete;用户页面不再只显示无上下文的“没有可显示内容”;`VOICE.md` 规定的“失败不写过会儿再打开”口径保持一致。
### T3 · 修复更新后的缓存与竞态
- account PATCH 成功后明确失效/重新验证 chart snapshot,至少按 account + profile version/真值指纹隔离;不得让旧 snapshot 在新资料已成功保存后长期冒充新结果。
- 检查 `refreshAccount` 与 chart request 的顺序,避免并发请求读到半更新 profile;engine cache key 继续包含 date/time/offset、ayanamsa、node mode 等已有必要维度。
验收:资料更新后重新进入 `/chart` 取得新 date/time/offset;失败时旧 snapshot 不覆盖已确认失效的 profile;同账户不同资料不会互相命中;现有 secondary-page cache 合同不被削弱。
### T4 · 补完整回归链路
至少覆盖:PATCH 后 chart-view 新资料、reported/accepted/confirmed、跨午夜、缺 active offset、query error、引擎 busy/timeout/bad payload、schema parse、旧 snapshot 失效、D1 planets/houses 合同。保留现有 `chart-view-route`、`chart-view-engine`、`server-owned-birth-profile`、`adopted-birth-date`、`account-api`、`secondary-page-entry` 测试名。
## 6. 让步顺序
1. T1 服务端真值一致性;2. T2 错误分类;3. T3 缓存/竞态;4. T4 全链路回归。若时间不足,不能以只改文案代替 T1;缓存优化可延期,但必须把旧快照风险记入进度和 `BLOCKED.md`。
## 7. 开工前置命令
```bash
git status -sb
git fetch origin --prune
git worktree add -b codex/chart-profile-update-consistency-20260922 .worktrees/chart-profile-update-consistency-20260922 origin/staging
cd .worktrees/chart-profile-update-consistency-20260922/frontend
./node_modules/.bin/tsc --noEmit
npm run lint
npm test
npm run build
```
开工时再次执行 `grep -n '^## BUG-' docs/BUG_HISTORY.md | tail -1`,若最大号变化,以当时最大号为准,不复用本文件预估号。
## 8. BUG 编号起点
本轮写任务书时 `docs/BUG_HISTORY.md` 最大号为 BUG-995。实现方若确认本现象属于新 Bug,开工前再次核对最大号,按最大号 + 1 连续编号;若只是 BUG-073/076 或 BUG-715~717 的复发,必须关联原记录,不得伪装成无关新 Bug。
## 9. 交付记录
代码实现同轮必须更新 `docs/BUG_HISTORY.md`、`docs/tasks/PROGRESS-chart-profile-update-consistency-20260922.md`;若有用户可见状态或文案变化,更新 `CHANGELOG.md`。验收未闭环前不得写 `resolved`,不得声称 staging 已部署。