docs: acceptance of fabe0114 round — two P0 in people archive, three fix briefs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
fabe0114dd
commit
3d689da996
@@ -0,0 +1,34 @@
|
||||
# TASK · 西洋盘 ASC / MC 标签与行星重叠 + 点击区过小 + 文档陈旧行(2026-09-25)
|
||||
|
||||
## 基线
|
||||
|
||||
- `origin/staging = fabe0114`(已部署)。分支 `codex/chart-western-fix-20260925`。只动 `frontend/src/components/chart-page/western-wheel-svg.tsx`、`frontend/src/lib/western-wheel-layout.ts` 与其测试、文档;与另两份修复单不交叉。
|
||||
- Claude 09-25 验收:星盘 / 星历修复(`19ea0f06`)与大运 / 西洋改版(`5a2d9da9`)逐项通过;两个 golden 已按真实引擎复算(Chara 逐字节一致;西洋 11 颗行星与 12 宫头一致)。以下是未通过项。
|
||||
|
||||
## 事故实证
|
||||
|
||||
- **P1**:ASC、MC 标签在 r=162(两层行星半径 136 与 188 之间)、偏离轴线 9°,**不参与避让**。排查用真实布局函数模拟 3000 张随机盘:「ASC」与行星标签重叠约 **34%**,「MC」约 3%,行星标签之间在启用第二半径后仍约 6%。典型情形是第 12 宫有行星、离上升点几度。1990 年测试盘上升附近恰好无行星,所以测试通过。违背本次改版"消除重叠"的目的。
|
||||
- **P3**:行星点击区 `r=22`(520 viewBox),375px 屏幕约 31px,低于 44px;西洋 fixture 是从真实值改写成视图键的子集(值真、形状手造,AGENTS §7.4 偏弱);`docs/BUG_HISTORY.md` BUG-1025 的修复 / 验证行与 `CHANGELOG.md`(首页拆分条目)仍写 `?settings=chart` 打开星盘资料,实际已跳 `/people`。
|
||||
|
||||
## 决策记录
|
||||
|
||||
- D1 ASC / MC 纳入避让集合(与行星同一轮松弛计算,轴点标签视为固定锚点、行星让位),或给轴点独立半径且与两层行星半径都保持 ≥ 字号的间距;二选一,写进 PROGRESS。
|
||||
- D2 避让测试改为**扫描**:用真实引擎生成至少 50 张虚构盘(或排查用的随机生成器 + 真实布局函数,固定种子),断言任意两标签(含 ASC / MC)包围盒不相交;允许的残余重叠率写成常量且 ≤ 1%。
|
||||
- D3 行星点击区在 375px 下 ≥ 44px(透明命中圆,不改视觉)。
|
||||
- D4 西洋 fixture 改为保存真实引擎原始响应,再由测试内的 mapper 转换;文档两处陈旧行更正。
|
||||
|
||||
## 硬红线
|
||||
|
||||
不改引擎与接口;不缩小字号到 < 12;相位线常显不变;骨架模式无文字不变;全量失败名单与基线逐条一致(Node 22 + Linux);既有断言三栏。
|
||||
|
||||
## 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/chart-western-fix-20260925 .worktrees/chart-western-fix-20260925 origin/staging
|
||||
cd .worktrees/chart-western-fix-20260925/frontend && npx tsx --test tests/western-wheel-layout.test.ts tests/chart-page-view.test.tsx
|
||||
```
|
||||
|
||||
## BUG 编号
|
||||
|
||||
沿用 BUG-1029 之后的号:若需记账用 people-archive-p1-fix 之后的下一个号,开工时核对。
|
||||
@@ -0,0 +1,78 @@
|
||||
# TASK · 星盘档案 P1 修复单:报告用错人(P0)、本人历史 500(P0)、切人时序(P1)(2026-09-25)
|
||||
|
||||
## 基线与现状
|
||||
|
||||
- `origin/staging = fabe0114`,**staging 已部署该版本**(deploy run 2897)。两个 P0 在 staging 上是**实况**。**修好之前不得提升 main。**
|
||||
- 分支 `codex/people-archive-p1-fix-20260925`。本单最优先,其它修复单可并行但不得碰下列文件。
|
||||
- Claude 09-25 验收:全量前端测试(Linux / Node 20)3851 条,失败 61 条;与基线 `514951d7` 的 56 条相比多 5 条,全是需要 Node 22 `mock.module` 的新测试(本机 Node 20 报 `ERR_MODULE_NOT_FOUND @/…`),门禁 run 2895(Node 22)为绿,**判为环境缺口,不算回归**。`next build`:`/` `/chart` `/ephemeris` `/people` 均 `○`,首屏 gzip 130,933 B 与基线相同。数据库迁移审查:跨用户读 / 删、伪造"已校正"都不可行。
|
||||
|
||||
## 事故实证
|
||||
|
||||
**P0-1 · 给别人生成报告,实际按户主资料计算且照常扣点**
|
||||
- `frontend/src/app/api/reports/route.ts` POST:`loadSubjectBirth(supabase, userId, requestedSubject)` 解析到了正确的人,报告行也存了该人的 `chart_profile_id`;但路由总是传 `jobs: createSupabasePersonalReportJobService(admin)` → `personal-report-route-core.ts` 走排队分支返回 202。
|
||||
- 真正生成在后台:`personal-report-worker-core.ts`(约 316 行)`const profile = await deps.loadProfile(job.userId)` → `personal-report-worker.ts` `loadProfile` 读 **`profiles`**(户主);还带上户主的校正候选范围。worker 两个文件本轮**没改**。
|
||||
- `subject-route-birth.test.ts` 只测失败路径,没测经 worker 的成功路径。违反 P1 单红线 1、3 与 D5。
|
||||
|
||||
**P0-2 · `GET /api/sessions`(默认本人)在自托管 Postgres 上 500**
|
||||
- `app/api/sessions/route.ts:29` `SELF_SESSION_FILTER = "chart_profile_id.is.null,chart_profile_id.eq.self"` 传给 `.or()`;客户端 `session-list-context.tsx:96` 每次都带 `subject=`,默认 `self`。
|
||||
- 自托管适配器 `frontend/src/lib/db/local-postgres-client-core.ts` `parsePostgrestOr` 只支持 `eq|neq|lt|gt|lte|gte`。**Claude 实测**:`parsePostgrestOr("chart_profile_id.is.null,chart_profile_id.eq.self")` → `THROWS: unsupported or filter: chart_profile_id.is.null`。结果:侧栏「聊天记录暂时无法读取」,本人历史消失。
|
||||
- **与 BUG-990 同类**(兼容层 `not(col,'is',null)` 未实现);BUG-990 的防复发写明"兼容层新增算子必须有真实 Postgres 覆盖,不得只加源码正则",本次 route 测试用的是 mock query builder,没拦住。
|
||||
|
||||
**P1-1 · 整页加载后,在人物列表返回前"当前人物"一律是本人**
|
||||
- `current-subject.ts` 只在 `bindCurrentSubjectAccount`(人物列表 fetch 完成后)才读 localStorage。于是:`/people`「和 TA 对话」整页跳 `/?newChat=1`,`NewChatDeepLink` 在账户和模型就绪时就触发,很可能早于 bind → 新对话绑成本人;「看星盘」「生成报告」整页跳转后先拉本人的盘 / 报告列表再切 → 闪现上一个人(违反红线 4)。
|
||||
|
||||
**P1-2 · 已打开对话的消息可能被清空**
|
||||
- `use-session-management.ts` 新增的订阅在每次 emit 时用第一页列表行(`messagesHydrated:false, messages:[]`)**替换** Home 的 `sessions`;`bindCurrentSubjectAccount` 在 id 就绪后总会 emit 一次。已加载的当前对话被换成空行,而 `ensureSessionMessages` 以 `activeSessionId` 为依赖、不重拉 → 对话内容变空;第一页之外或 URL 打开的会话被丢。`SessionListProvider` 每次 emit 还 `setSessions([])` → 侧栏闪空。
|
||||
|
||||
**P2**
|
||||
1. 迁移回填把旧 jsonb 里客户端可随意写的 `accepted` / `confirmed` 与 `active_*` 抄进类型化列 → 未经校正的值变成"已校正"。
|
||||
2. 标题切换器的人物列表按页面加载缓存(`loadSubjectCatalog`),`/people` 增删改后不刷新;删掉的人仍可选。
|
||||
3. `/people` 删除确认在用量请求失败时显示「0 个对话和 0 份报告」,不可逆操作前给出错误数字。
|
||||
4. 今日星语是否加载用的是户主的 `profileComplete` / `natalMinuteAvailable` / `profile.timezoneId`;户主缺分钟时别人的卡片被压掉;客户端指纹用户主资料 + 人物 id,改别人资料后当天卡片不更新。
|
||||
5. 「和我合盘」把当前人物切成对方,后续对话可能绑成对方,而问题文本里的「我」是本人。
|
||||
6. `ab6c55f8` 在星历挂载时 `cache.current.clear(); invalidateEphemerisPage()` → 暖进也多拉一次 `?date=`(两轮引擎);首屏刷新失败(429 / 坏包)后永远停在「这一天的星历还没拿到。」,无重试。
|
||||
7. `fabe0114` 约 11 处改动断言没有「原值 / 新值 / 原因」(`session-list-provider`、`personal-report-api`、`settings-mvp-contract`、`chart-view-route`、`server-owned-birth-profile`、`secondary-page-entry` 等),PROGRESS 写「见各测试文件」但文件里没有。
|
||||
|
||||
**P3**:接口 5 人预检在自托管上无效(适配器忽略 `count/head`,靠触发器兜底,触发器计数无锁);非 uuid 人物 id → 数据库错误 / 500 而不是 404;报告 POST 同时收 `subjectId` 与 `chartProfileId` 可能不一致;`chart-library-panel.tsx` 已无入口仍保留且 Python 合同测试还在断言它;`/people` 编辑时表单标题仍是「添加一个人」。
|
||||
|
||||
## 决策记录
|
||||
|
||||
- D1 worker 必须按报告行的 `chart_profile_id` 经 **`loadSubjectBirth` / `resolveSubjectBirth`** 取出生资料(红线 3:唯一解析入口);校正候选范围只在本人时使用(沿用 consult 口径)。人物已删 → 任务失败并**退点**(沿用既有失败退点路径),不回落本人。
|
||||
- D2 兼容层 `parsePostgrestOr` 增加 `is` 算子(`is.null` / `is.true` / `is.false`,编译为 `is null` / `is true` / `is false`,**不得写成 `= null`**),与 BUG-990 的 `not … is` 同口径;必须有**真实 Postgres** 测试覆盖。不改路由语义。
|
||||
- D3 当前人物在模块加载时**同步**从 localStorage 读出(按上次账户 id 键;账户未知时先读"最后账户"键),`bindCurrentSubjectAccount` 只做校验与纠正;新建对话深链、星盘 / 星历 / 报告首屏请求**等 bind 完成**再发。
|
||||
- D4 订阅 emit 改为**合并**进 `sessions`:保留已 hydrated 的会话与消息;人物未变不 emit;Provider 不再 `setSessions([])` 清空,换人时用新人物的列表整体替换一次即可。
|
||||
- D5 回填纠偏:新迁移把由 jsonb 回填而来的 `birth_time_status ∈ {accepted, confirmed}` 降为 `reported`、`active_*` 置空(这些值从未经过校正流程),写明理由;不动户主 `profiles`。
|
||||
- D6 其余 P2 / P3 按上表逐条修;「和我合盘」不改当前人物(合盘对话绑定本人,问题里写对方名字);删除确认在用量未知时禁用删除并提示「暂时查不到这个人的对话数量,稍后再试」。
|
||||
|
||||
## 硬红线
|
||||
|
||||
1. 失败名单与开工基线(`fabe0114`)**逐条一致、新增 0**,必须在 **Node 22 + Linux** 跑(门禁环境);进度记录附对比命令与结果。**推 staging 前必须跑全量**(上一轮只跑定向,门禁红了 3 次)。
|
||||
2. P0-1、P0-2 各自至少一条**真实路径**测试:P0-1 用 worker 成功路径(注入 fake engine,断言引擎收到的是他人的出生资料、户主数据未出现);P0-2 用 `npm run test:db` 真实 Postgres 断言 `subject=self` 返回存量 `null` / `self` 行、不返回他人行。
|
||||
3. 每条改动的既有断言写三栏,包括补齐 `fabe0114` 缺的约 11 处。
|
||||
4. 不改已验收的产品口径(5 人、无关系、标题切换、历史按人);不改 workflow。
|
||||
|
||||
## 任务分解
|
||||
|
||||
- T1 worker 按人取资料 + 失败退点(P0-1)。
|
||||
- T2 兼容层 `is` 算子 + 真实 Postgres 测试(P0-2)。
|
||||
- T3 当前人物同步读取与请求闸门(P1-1)。
|
||||
- T4 会话列表合并而非替换、Provider 不清空(P1-2)。
|
||||
- T5 回填纠偏迁移(P2-1);切换器在 `/people` 变更后刷新(P2-2);删除计数失败禁用(P2-3);今日星语按当前人物判定与指纹(P2-4);合盘不切人(P2-5);星历暖进不重复拉取 + 首屏失败可重试(P2-6);补三栏(P2-7)。
|
||||
- T6 P3 逐条;删除 `chart-library-panel.tsx` 与只测它的断言。
|
||||
- T7 记录:BUG 新号(P0-1 报告用错人、P0-2 本人历史 500 复发自 BUG-990),BUG-1030 状态改回 investigating 直至真机清单;PROGRESS;更新 `docs/testing/people-archive-p1-20260924.md`(加:给朋友生成报告后打开报告核对出生资料;本人侧栏历史可见;/people 点「和 TA 对话」新对话标题旁是 TA 的名字;在别人的对话里刷新页面后仍是 TA)。
|
||||
|
||||
## 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
node -v # 必须 22.x;不是就先切到 22 再跑测试
|
||||
git worktree add -b codex/people-archive-p1-fix-20260925 .worktrees/people-archive-p1-fix-20260925 origin/staging
|
||||
git worktree add --detach .worktrees/p1fix-baseline origin/staging
|
||||
cd .worktrees/p1fix-baseline/frontend && npm test > /tmp/p1fix-base.log 2>&1
|
||||
cd ../../people-archive-p1-fix-20260925/frontend && ./node_modules/.bin/tsc --noEmit && npm run lint
|
||||
npm run test:db # 需 Docker
|
||||
```
|
||||
|
||||
## BUG 编号
|
||||
|
||||
写单时最大 BUG-1030;本单从 **BUG-1031** 起,开工时核对。
|
||||
@@ -0,0 +1,54 @@
|
||||
# TASK · 报告读者版修复单:年运 Year Lord / Muntha 全是「-」+ 投影误删 Bhava Bala(2026-09-25)
|
||||
|
||||
## 基线
|
||||
|
||||
- `origin/staging = fabe0114`(已部署)。分支 `codex/report-reader-main-fix-20260925`。与 people-archive-p1-fix 不交叉(本单只动 `scripts/` 与 `report-public-projection.ts`),可并行。
|
||||
- Claude 09-25 验收 `3c2f7bd5`:读者版导入与上游 `23b9609e` 逐函数一致;虚构生日(1990-01-01 12:00 北京)生成读者版 1929 行,D5 全部泄漏词 **0 命中**;KP 与三项 transit 在 `type('Args')` 参数下不再 blocked;`birth_asc_sign_idx` 已补,太阳回归 Muntha 随年份变化(双鱼 → 白羊 → 金牛)、Year Lord 木星 → 火星 → 金星;Python 定向 183 条全绿。以下是未通过项。
|
||||
|
||||
## 事故实证
|
||||
|
||||
**P1-1 · 两边一致也判"冲突"**:`scripts/annual_tajika_pack.py` `_annual_comparable_value("year_lord")`:太阳回归侧给 `{year_lord: Jupiter, year_lord_sign: Pisces}`,tajika 侧给 `{year_lord: Jupiter, year_lord_sign: None}`(它的字典里是 `muntha_sign` 而不是 `year_lord_sign`)→ 比较失败 → 2026 / 2027 / 2028 全是 `status: conflict`(木星 / 木星、火星 / 火星、金星 / 金星)。参考版仍印「Year Lord 仍要带着分歧标签阅读」。该函数原样来自上游,上游有同样弱点;单测只用键集相同的合成字典,所以通过。
|
||||
|
||||
**P1-2 · 读者版年运章 Year Lord / Muntha 全是「-」**:读者版读 `annual.year_lord.data.{year_lord, muntha_sign, selection_basis}`;`year_lord` 是没有 `data` 的冲突字典 → Varshesha、选取依据、年度上升、Muntha 星座**每年都是「-」**,未来年份 Varshapravesha 也是「-」(排查实测与入库 golden `frontend/tests/fixtures/report-reader-main-fictional.json` 一致)。即使修好冲突,`data` 取太阳回归值也没有 `muntha_sign`。上游用 `tajika.calc_panchadhikari_year_lord` 填这些字段,本仓从未同步。Python 测试只查表头里有 "Year Lord" "Muntha" 字样。**用户能看到的年运结论仍不可用**,`docs/testing/report-reader-main-20260924.md` 第 3 条无法通过。
|
||||
|
||||
**P2-1 · 投影误删真实章节**:`projectOrdinaryReportMarkdown` 作用于读者版 golden 时整段删掉 `### Bhava Bala 十二宫力量`(标题 + 12 行表,15 行):旧 `tableIsInternal` 把表头 `Score` 当内部词,新 `adjacentInternalTableIndexes` 连前面的标题一起删。D5 只要求删说明段,不删标题;且标题后若还有正常表格会挂到错误章节下。
|
||||
|
||||
**P2-2** 新泄漏规则(D5 词表 + 12 个英文单词规则)同时作用于 `fenceIsPublic`、`isAllowlistedSvg` 与 `projectChatExportMarkdown`,会删掉聊天导出里的英文行。
|
||||
|
||||
**P3** 读者版五要素表仍露原始键(`overall_score`、`吉性_count`、`total_elements`);姓名行显示「姓名:-」。
|
||||
|
||||
## 决策记录
|
||||
|
||||
- D1 `_annual_comparable_value("year_lord")` 只比较 `year_lord`(行星);星座字段一侧缺失时不参与比较。在本仓注明与上游的差异与原因。
|
||||
- D2 读者版年运表数据来源:Varshesha = 太阳回归侧 `year_lord`(D1 后两侧一致时取之,冲突时标注两者),Muntha 星座 = `muntha.data.muntha_sign`,年度上升 = 太阳回归上升;**优先从上游同步 `calc_panchadhikari_year_lord`**(整段引入并注明来源提交),同步不可行时用本地已有字段拼,不得编造。
|
||||
- D3 投影:`Score` 等通用英文表头不作为内部判据;删内部表时只删紧邻说明段,**不删标题**。
|
||||
- D4 新泄漏规则只用于报告正文投影,不作用于 `projectChatExportMarkdown`(聊天导出沿用原规则)。
|
||||
- D5 五要素表原始键映射为中文或删除该列;姓名缺失时整行不输出。
|
||||
|
||||
## 硬红线
|
||||
|
||||
1. 不改 Ayanamsa / 宫制 / 大运口径;不改上游算法(D1 的比较口径除外,必须注明)。
|
||||
2. golden 必须由真实引擎重新生成(虚构生日),新增断言:读者版年运章至少两年的 Varshesha 与 Muntha 单元格**不是「-」且彼此不同**;读者版 golden 投影后仍含 `Bhava Bala` 标题与表。
|
||||
3. 读者版投影后 `ordinaryOutputLeaks = []` 不得弱化。
|
||||
4. `jyotish_api_server.py` 不增长;Python 快速门与定向测试必跑;前端全量失败名单与基线逐条一致(Node 22 + Linux)。
|
||||
|
||||
## 任务分解
|
||||
|
||||
- T1 比较口径(D1),单测用**真实引擎**两侧字典。
|
||||
- T2 读者版年运表数据(D2),含是否同步上游 `calc_panchadhikari_year_lord` 的决定写进 PROGRESS。
|
||||
- T3 投影(D3、D4)与五要素 / 姓名行(D5)。
|
||||
- T4 记录:BUG-1028 补"读者可见结果未修"并关联本单;BUG-1026 补投影误删;PROGRESS;更新真机清单。
|
||||
|
||||
## 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
|
||||
git worktree add -b codex/report-reader-main-fix-20260925 .worktrees/report-reader-main-fix-20260925 origin/staging
|
||||
cd .worktrees/report-reader-main-fix-20260925
|
||||
python3 -m pytest -q tests/test_report_reader_main.py tests/test_annual_tajika_pack.py
|
||||
```
|
||||
|
||||
## BUG 编号
|
||||
|
||||
沿用 BUG-1026 / 1028,不新开号。
|
||||
Reference in New Issue
Block a user