merge origin/staging into the UI kit fix (issue #111); renumber BUG-1444..1450 to 1448..1454

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LutgzyJqNhPpZy1nFsJtN3
This commit is contained in:
Jesse_Chen
2026-10-27 09:55:57 +08:00
co-authored by Claude Opus 5.5
35 changed files with 1630 additions and 43 deletions
+71 -7
View File
@@ -19626,7 +19626,71 @@
- 复发自:无
- 修复版本:分支 `codex/full-data-parity-3-20261022`。
## BUG-1444 | 桌面加载后整页被卸掉再挂上
## BUG-1444 | 星盘页不说上升会不会因为时间误差换座
- 状态:resolved
- 首次发现:2026-10-27
- 最近更新:2026-10-27
- 影响面:星盘页页头。本人和人物档案里每个人的星盘页。不扣点,不调模型。
- 用户现象:资料里已经写了时间有多准,星盘页却不告诉你,按这个精度上升星座会不会换。
- 触发条件:打开一张还没采用校正结果的星盘。医院记录、家人记得的钟点、大概时间、只知道时段、不知道时间,都会算。已经采用或确认的校正时间,以及旧资料导入,不显示这一句。
- 根因:整段时间里上升换不换,计算早就有,但只用在生时校正里。星盘页没把结果说出来。
- 修复:星盘和这段计算一起做。算出来就在出生资料下面写一句。算不出来、超时或资料不够,这一句不出现,星盘照常打开。上升已经确定时没有校正链接。
- 验证:`frontend/tests/lagna-precheck.test.ts`、`frontend/tests/lagna-precheck-chart.test.ts`、`frontend/tests/chart-page-view.test.tsx` 里这一句的四条文案。没有登录浏览器,不把页面走查写成通过。
- 防复发:预检失败必须整行不显示,并且不能让星盘请求失败。窗口超过接口上限时截到 1441 分钟。
- 相关记录:BUG-1445。issue #112。
- 复发自:无
- 修复版本:分支 `codex/lagna-precheck-20261027`。
## BUG-1445 | 校正开场不讲这一步做不到什么
- 状态:resolved
- 首次发现:2026-10-27
- 最近更新:2026-10-27
- 影响面:生时校正的第一句开场。
- 用户现象:开场只讲怎么做,不讲能不能精确到某一分钟,也不讲说不准或中途停下会怎样。
- 触发条件:开始一次生时校正,读第一段开场。
- 根因:固定开场和给模型的说明都只有「做什么」和「怎么做」两层。
- 修复:加上限度:能把用来解读的星盘定下来,但不保证精确到某一分钟;对不上就直接说不准,照实记,不换个说法圆回来;中途可以停,照原来填的时间用。模型没写这层就换回这几句固定话。
- 验证:开场文案测试已按新句数改过并通过。模型缺限度句时判定为不合格,从而换回固定句。
- 防复发:合格开场必须同时有「不保证」或「精确到某一分钟」,以及「不准」。行话清单没有放宽。
- 相关记录:BUG-1444、BUG-1257、BUG-1049。issue #112。
- 复发自:无
- 修复版本:分支 `codex/lagna-precheck-20261027`。
## BUG-1446 | 星盘页的校正链接在已有校正时直接报错
- 状态:resolved
- 首次发现:2026-10-27
- 最近更新:2026-10-27
- 影响面:本人星盘页上「出生时间校正」链接。上升会换的人最容易已经开过一次校正。
- 用户现象:点这个链接,已经有一次没做完的校正时,页面报「仍有未完成的校正」,回不到那一次。
- 触发条件:校正还在进行,从星盘页打开 `/?rectify=1`。
- 根因:这个链接走的是「新开一次」的意图。数据库在已有可续校正时拒绝新开,并抛出冲突。首页入口用的是另一种意图:有就续上,没有就新建。
- 修复:星盘页链接改走首页入口的同一条路,不新建意图,不改数据库。重新开始校正的按钮仍是新开。
- 验证:`frontend/tests/lagna-precheck-rectify-entry.test.tsx`。已有校正时请求意图是 homepage,不出现冲突句;没有时同样是 homepage,由服务端新建。
- 防复发:星盘页入口不得再调用「新开一次」。冲突句只留给真的新开。
- 相关记录:BUG-1444。issue #112 第 1 次打回。
- 复发自:无
- 修复版本:分支 `codex/lagna-precheck-20261027`。
## BUG-1447 | 别人的星盘页也放了校正链接
- 状态:resolved
- 首次发现:2026-10-27
- 最近更新:2026-10-27
- 影响面:人物档案里其他人的星盘页页头。
- 用户现象:别人的星盘上也有「出生时间校正」。点进去只会说校正暂时只支持本人,是个没用的入口。
- 触发条件:打开人物档案里另一个人的星盘,上升会换,或不知道出生时间。
- 根因:这一句对所有星盘都加了链接。校正只做本人,链接在别人的页面上没有去处。
- 修复:不是本人时,句子停在换座时刻或「上升星座定不下来。」,不写校正,也不放链接。本人不变。
- 验证:`frontend/tests/chart-page-view.test.tsx` 里非本人两种情况没有链接、没有「出生时间校正」;本人仍有。`frontend/tests/lagna-precheck.test.ts` 锁住这两句。
- 防复发:非本人的页头句子不得再出现校正链接。
- 相关记录:BUG-1444、BUG-1446。issue #112 第 1 次打回。
- 复发自:无
- 修复版本:分支 `codex/lagna-precheck-20261027`。
## BUG-1448 | 桌面加载后整页被卸掉再挂上
- 状态:resolved
- 首次发现:2026-10-26
@@ -19642,7 +19706,7 @@
- 复发自:无
- 修复版本:分支 `codex/ui-kit-onboarding-fix-20261026`。
## BUG-1445 | 报告和合盘的中英切换看不出选中了哪个
## BUG-1449 | 报告和合盘的中英切换看不出选中了哪个
- 状态:resolved
- 首次发现:2026-10-26
@@ -19658,7 +19722,7 @@
- 复发自:无
- 修复版本:分支 `codex/ui-kit-onboarding-fix-20261026`。
## BUG-1446 | 一次性提示对每次页面变化都扫整页
## BUG-1450 | 一次性提示对每次页面变化都扫整页
- 状态:resolved
- 首次发现:2026-10-26
@@ -19674,7 +19738,7 @@
- 复发自:无
- 修复版本:分支 `codex/ui-kit-onboarding-fix-20261026`。
## BUG-1447 | 启程动效对所有人播放,慢网时先把内容藏起来
## BUG-1451 | 启程动效对所有人播放,慢网时先把内容藏起来
- 状态:resolved
- 首次发现:2026-10-26
@@ -19690,7 +19754,7 @@
- 复发自:无
- 修复版本:分支 `codex/ui-kit-onboarding-fix-20261026`。
## BUG-1448 | 启程清单关掉后仍翻全部报告,加人后不打勾
## BUG-1452 | 启程清单关掉后仍翻全部报告,加人后不打勾
- 状态:resolved
- 首次发现:2026-10-26
@@ -19706,7 +19770,7 @@
- 复发自:无
- 修复版本:分支 `codex/ui-kit-onboarding-fix-20261026`。
## BUG-1449 | 拖动排序一次发很多请求,新对话掉到组底
## BUG-1453 | 拖动排序一次发很多请求,新对话掉到组底
- 状态:resolved
- 首次发现:2026-10-26
@@ -19722,7 +19786,7 @@
- 复发自:无
- 修复版本:分支 `codex/ui-kit-onboarding-fix-20261026`。
## BUG-1450 | 组件有两套类名函数,验证码输入版本不固定
## BUG-1454 | 组件有两套类名函数,验证码输入版本不固定
- 状态:resolved
- 首次发现:2026-10-26
@@ -0,0 +1,85 @@
# 星盘界面对标竞品:拆解与方案(issue #114,2026-10-27)
产品负责人 10-27 转来某竞品 13 张截图(星盘页、盘面检视、深读四个页签、对话页右侧盘面),要求「按这种来做」,先按业务拆开、逐项把需要他定的事说清,全部定了再开工。截图里有一张含真实出生资料,本文不引用。
我方现状来自 staging `009456d8e` 代码盘点(`frontend/src/components/chart-page/*`、`chat-chart-frame.tsx`、`chart-view-*.ts`)。
## 0. 总体对照
| 竞品 | 我方今天 |
| --- | --- |
| 一页铺开:左边大盘 + 盘面检视,右边九曜表 / 宫位主题 / 大运条 / 命盘速览,下面「深读」四个页签 | 四个页签(星盘 / 基础信息 / 大运 / 西洋盘),每次只看一块 |
| 南印度方盘为默认,可切北印度菱形盘 | **只有北印度菱形盘** |
| 点星 / 点宫:盘上画宫主线和视相线、表格同行高亮、检视面板展开 | 点星只弹一个文字气泡;西洋盘有相位线联动,印度盘没有 |
| 盘上可叠「八宫点 / 宫力 / 行运」图层 | 没有图层;行运是单独一种盘型 |
| 六力、宫力、八宫点、瑜伽、出生历法都有可视化 | **引擎都算了(有接口),星盘页一样都没接** |
| 大运三层(大运 / 分运 / 子运)带进度条,等比长卷可逐层展开,可换观测日期 | 两层(大运 → 子运),子运日期是前端按年数比例拆的,没有进度、不能换日期 |
| 对话页右侧是完整可点的盘 + 检视 + 九曜表,空对话给按盘出的问题 | 右侧只有一张不能点的 D1 小图,默认收起,手机没有 |
竞品也有没做好的地方:「宫主流向」整列「未提供」,六力「门槛未提供」,瑜伽把大量「未满足」也列出来——这些我们引擎都有数据,可以做得更完整、更干净。
## 1. 业务拆分(每块一张任务书,按顺序)
### M1 盘面本身
- 新做南印度方盘(固定星座格、上升斜线、中心大字「上升 巨蟹」样式、度数上标、旺 / 陷 / 逆标记),与现有北印度盘可切换,记住用户选择。
- 盘型条沿用现有 23 种(D1~D60、月亮盘、宫位盘、行运)。
- 中心显示当前三层大运小标签。
- 图层:无 / 八宫点(每宫角落显示点数,高于 28 金色、低于蓝色)/ 宫力 / 叠加行运(行运星以浅色叠在本命盘上)。
### M2 点选联动 + 盘面检视
- 点星:该星所在格高亮,其余变淡;实线连到它主管的宫,虚线连到它视相的宫;中心改显示这颗星;右侧表格同一行高亮。
- 检视面板:星座内位置条(0°~30°,标月宿分界)、月宿、尊贵刻度(陷 → 中 → 旺)、六力(对门槛的百分比)、视相宫位、主管大运区间、此刻行运位置;按钮「问 AI:这颗星」「在 D9 定位」。
- 点宫 / 点「宫位主题」小签:该宫高亮,面板显示宫主、宫内星、宫力、八宫点。
- 键盘 ← / → 切换、Esc 收起(桌面)。
### M3 命盘速览 + 顶部小签
- 速览卡:上升(度分)、月亮星座与月宿、灵魂星(Atmakaraka,写中文)、当前大运 › 分运(带进度条与结束日)、六力最强、需留意(最弱或落陷)。
- 页头小签:上升 / 月亮 / 太阳 / 当前大运,点了在盘上定位。
- 与 #112 的「上升确定 / 可能换座」那一行放在一起。
### M4 时运流年
- 观测日期:日期选择 + 上月 / 下月 / 上年 / 下年 / 此刻;换日期后大运进度、行运表、叠加图层一起更新。
- 当前运期三层(大运 / 分运 / 子运):起止日期、已过百分比、剩余时长。
- 九曜行运表:星座度数、从上升起第几宫、从月亮起第几宫、该宫八宫点;土星七年半状态。
- 人生长卷:三行等比条(大运 / 该大运的分运 / 该分运的子运),点哪段展开哪段;「叠到盘面」。
- 需要引擎补:子运第三层(目前前端按比例拆,需改用引擎值)、任意日期行运(接口已有)。
### M5 能量图谱
- 行星六力:每星一条总量 + 六段分量(自然 / 位置 / 方位 / 时间 / 运动 / 视相),竖线为门槛,右侧百分比。
- 宫位力量柱状图,均值虚线,点柱选宫。
- 八宫点矩阵:按宫位 / 按星座;原始 / 三角削减 / 同主削减三种口径切换;格子按点数深浅着色。
- 数据:引擎已有 `/api/shadbala`、`/api/bhava_bala`、`/api/ashtakavarga`,需接进星盘页。
### M6 命性格局(瑜伽)
- 组合列表:名称、涉及行星、状态(条件满足 / 部分满足);点一条在盘上高亮涉及的星。
- 引擎 `/api/yogas` 是否给「部分满足」需开工前核对。
### M7 排盘底册
- 出生资料与计算口径(岁差、宫制、交点)、出生历法(提毗、羯罗那、常瑜伽、日出日落、月出、当时行星时)与各要素下次交界时刻、行星名册、宫主流向(第 N 宫之主 → 落第几宫)。
- 历法数据:星历页已有五要素,日出日落 / 行星时 / 交界时刻需引擎补。
### M8 对话页右侧盘面
- 右栏换成可点的完整盘(M1 + M2 的窄版):顶部小签、盘、检视、九曜表;「换一盘」切人物档案里的人。
- 空对话中间显示「盘面已带入」+ 按这张盘出的 4 个示例问题。
- 检视面板「问 AI:这颗星」直接在当前对话里发问。
## 2. 顺序与依赖
- #111(组件库修复)、#112(星盘页页头一行)都在改星盘页,**本需求排在它们合入之后**。
- 建议分三批:
- **第一批**:M1 + M2 + M3 + M8(看得见、用得最多)。
- **第二批**:M4 时运流年。
- **第三批**:M5 + M6 + M7(数据型)。
- 执行:按任务书模式交 Grok,Claude 验收;一次揭幕、首屏 gzip ±2%、`page.tsx` 不增状态等红线照旧。
## 3. 需要产品负责人定的事
见 issue #114 评论(Q1~Q9)。
@@ -0,0 +1,51 @@
# 竞品「推断前事」调研(issue #112,2026-10-27)
产品负责人 10-26 转来某竞品的「推断前事 / 验前事」页面全文(真实用户的盘,本文只描述做法,不抄其中的盘面结论与推导),问三件事:它怎么做、能不能收敛、我们能不能做到。
## 1. 它怎么做
| 步骤 | 内容 |
| --- | --- |
| 定位 | 开头写明:用来**确认上升星座(Lagna)对不对**,**不能**把出生时间校准准;判断多数对得上只说明上升「很可能对」,不证明时间准确;报告照用户填的时间写,不因这一步改 |
| 出题 | 一次给 **6 条**断语:2 条本命静态(父亲、母亲,按 9 宫 / 4 宫宫主与太阳、月亮的状态)+ 4 条带年份的事件(按 Vimshottari 当前大运下各小运窗口 1~3 年,读该小运主星掌管与落入的宫) |
| 透明度 | 每条附一句白话理由,可展开「原始推导」(宫主、落宫、尊贵、小运) |
| 作答 | 每条三选:准 / 部分准 / 不准;可选补充;明确「不准就记不准,不会换说法圆回来」 |
| 结果 | 只给「本轮吻合 x/6」,说明没对上可能是模型没看准、也可能是时间有偏差;**两条路都放行**(照填写时间继续,或找人工校准) |
| 上升交界 | 上升压在星座交界时,「必要时会换个上升再比一轮」 |
| 模型 | 自述是「小模型的快速预判」,后面会换更强的模型 |
## 2. 能不能收敛
**不能,而且它自己也没打算收敛。** 理由三条:
1. **没有被比较的候选。** 它只对「用户填的那个时间」出一组断语,打一个吻合分;没有第二个上升或第二个时间参与比较(交界时才比一轮)。没有候选之间的比较,就谈不上收敛,只是一个「可信度提示」。
2. **带年份的四条,时间窗口与上升无关。** Vimshottari 大运 / 小运的起止只由出生时月亮的星宿决定,换上升不换窗口;换上升只改「这个小运读成什么事」。而这类事件(某三年里有重要感情、某年因工作搬家、某年关系突变、某年事业退一步并有花销)对成年人的基础发生率本来就高,用户多半会答「准 / 部分准」,**吻合分对上升的区分力很弱**。
3. **我们自己量过同类信息的区分力。** 在 77 例公开名人盘(v5 评价集)上:
- 用户口述的经历几乎分不开候选:57 件日精度经历里能把候选分开的只有 4~14 件(`docs/research/` 09-29 研究,BUG-1089 按设计关闭);
- 10-16 复现网上流行的「象征星小运区间求交」法:分钟级与随机对照无差别,上升星座二选一略好于随机但不显著(z≈1.3);
- 真正有区分力的是我们现在的做法:**引擎按候选出选择题、逐题比较**,六题后 ±10 分钟窗口里 D1 上升命中 76/77(`docs/research/rectification_varga_resolution_2026_09_30.md` M1)。
所以竞品的 4/6 这类分数,主要反映「断语写得是否宽泛」,而不是「上升是否正确」;它把这一点诚实地写在了页面上。
## 3. 我们能不能做到
**能,而且我们已经有比它强的那一半;值得学的是它的「说法」和一个很便宜的预检。**
| 竞品做的 | 我们现状 | 判断 |
| --- | --- | --- |
| 确认上升对不对 | 生时校正六题后 ±10 窗 D1 上升命中 76/77;±10 窗里 64/77 例**整窗只有一个上升**(不用问就能确认) | 我们更强,而且大多数人**根本不用问** |
| 6 条宽泛断语 + 吻合分 | 不做吻合分;选择题由引擎在候选之间出 | 不建议照搬:区分力弱,还会让用户以为「4/6 = 时间基本对」 |
| 开头讲清楚限度、「不准不圆」 | 校正开场有说明,但没有这么直白的「这一步不能做什么」 | **值得学** |
| 每条附白话理由 + 可展开原始推导 | 选择题不附理由 | 可学,但只能在答完之后展示(答前展示会诱导作答) |
| 上升压交界时换上升再比 | 采集页按用户的时间精度扫窗口;没有单独的「交界预检」 | **值得做**:纯计算、不问问题——窗口里上升不换,就直接告诉用户「上升确定」;窗口跨交界,才引导去校正 |
| 两条路都放行 | 一致(不强制校正) | — |
## 4. 建议(交产品拍板)
- **A(推荐)**:不做吻合分。做两件小事:
1. **上升交界预检**:用户填时间 + 精度后,纯计算判断精度窗口内上升是否换星座;不换就在星盘页 / 首页说一句「按你给的时间精度,上升星座是确定的」,换就给出「上升可能是 X 或 Y」并引导校正。不调用模型、不新增问题。
2. **校正开场文案**照竞品的诚实口径改写:这一步能做什么、不能做什么、答「不准」就记不准。
- **B**:照做「6 条快速预判 + 吻合分」作为入口体验。前提是先在 77 例上量:真上升与相邻上升的吻合分差多少;差异不显著就不上线(预计不显著,见第 2 节)。
- **C**:都不做。
选 A 时由 Claude 写任务书交循环;选 B 先出研究单。
@@ -0,0 +1,78 @@
# 语气对比:我方报告 / 对话 vs 竞品解读(issue #113,2026-10-27)
产品负责人 10-27 转来某竞品对一张真实盘的完整解读(朋友评价「像占星师说的话」),说我方「agent 输出和报告输出的语气用户看不懂」,要求先查问题、做对比,敲定后由 Claude 改。竞品原文含真实个人资料,**本文只描述写法,不引用其中的盘面结论**;我方样本全部来自虚构盘或公开名人盘。
## 1. 样本
| 样本 | 来源 | 说明 |
| --- | --- | --- |
| 竞品 | #113 正文,约 9,300 汉字 | 章节:总评、性格与内在、事业、财富、情感、健康、灵性成长、行动建议、命盘结构、需留意的组合、大运解读 |
| 我方报告 | 虚构 0 号盘,完整数据版中文,staging `cef7b317a` 生产渲染路径 | 192 万字符、88 章 |
| 我方对话 | 名人回测 round4(10-02,Jobs 事业 / 婚恋)+ 10-01 新提示词(Obama 父母) | **都早于 10-06 去标题、10-07 姐姐口吻与提示词瘦身**;仓库里没有更新的整段真实回答 |
## 2. 数字(每千汉字)
| 样本 | 外文词 | 括注 | 「可能 / 或许 / 多半」类 | 「你」 | 表格行占比 |
| --- | --- | --- | --- | --- | --- |
| 竞品 | 12.2 | 8.7 | **0.5** | 12.8 | 0% |
| 我方报告·大运解释段 | 5.2 | 8.1 | **27.4** | **0** | 0% |
| 我方报告·全文 | 15.6 | 5.0 | 14.8 | **0** | **91%** |
| 我方对话(旧样本) | 0.3 | 10.4 | 1.3 | 16.0 | 0% |
## 3. 竞品为什么读起来像占星师
1. **每段一条链:盘面 → 机制 → 生活里的样子。** 先点出一个配置,用一句话说它为什么这样起作用,再落到「你在工作 / 家里 / 钱上会怎样」。
2. **术语当「招牌」用,第一次出现带中文括注。** 例如「全盘唯一的功能大吉星(Yogakaraka)」。读者不需要懂,但会感到「有门道」。
3. **有张力、有化解。** 「然而……」「化解之道在于……」「先……后……」,把几条盘面因素编成一个人的故事,而不是逐项列条件。
4. **按人生领域分章,开头有总评。** 用户最想读的「我是什么样的人、事业、钱、感情、健康、现在这几年」各有一章。
5. **大运是叙事。** 给出具体起止日期,每个子运说「这段的焦点是什么、接下来会转向什么」。
6. **第二人称、语气笃定**,全文几乎不出现「可能」。
竞品的问题(**不学**):
- 健康章直接写出具体病名倾向,财富章写「严禁某类投资」——与我方红线(医疗、投资不下确定结论,AGENTS Part B4)冲突。
- 「先苦后甜」「宿命式」这类确定性断语,没有任何不确定性提示。
- 同一段「性格」在页面上重复了三次,排版有缺陷。
- 辞藻偏重(「咆哮」「烟消云散」),信息密度不如看上去高。
## 4. 我方问题
### 4.1 报告(主要问题)
报告**不是模型写的**,是引擎模板拼出来的(`scripts/pl9_interpretation_packs.py`),这是「看不懂」的主因:
1. **没有解读正文。** 没有总评、没有性格章;88 章里 91% 的行是表格。最接近「性格」的是逐颗行星的条件说明。
2. **每句都在免责。** 大运段的模板是「这段时间可能突出的主题:传统阅读里,X 容易把……推到眼前。条件好时可能……受压时可能……怎么细读:先核对……」,对每一个主运、子运、次子运重复。「可能」类词的密度是竞品的约 55 倍,全文没有一个「你」。
3. **内部口径直接写给用户。** 例如「功能吉凶用本仓功能吉凶层,不另做一套判断」「取消条件以检测器返回的说明为准,这里不新判」「六维力量合计为 9.9407」,表格里还有 `mars_house=2;severity=中等` 这种字段名。
4. **术语政策与对话相反。** 对话禁梵文外文;报告的术语白名单(`pl9_language_terms.py` 的 `ZH_ALLOWED_LATIN_TOKENS`)专门保留 Dasha、Shadbala、Ashtakavarga、Vimsopaka 等外文,且不加解释。罗睺在报告里叫「北交点」,在对话里叫「罗睺」。
5. **重点卡只有字段值**(中性、入庙、功能凶星)加一句免责,没有一句结论。
### 4.2 对话(次要,需先拿到现行样本)
- 规则层面(`frontend/src/mastra/product-voice.ts`、`frontend/docs/VOICE.md`)已经要求先给结论、第二人称、一段最多一个术语、不读心,旧样本的「你」密度、免责密度已接近竞品。
- 旧样本的问题:括号里塞一串依据(「木星 10 宫、力量最强一档;兼 4 宫与 7 宫主;事业分盘第 11 宫」),读者跳过括号后剩下的是结论,但**缺「为什么」那一环**;竞品是把「为什么」用一句白话写进正文。
- 10-06 / 10-07 之后的现行输出仓库里没有存档,判断现行对话前需要一份 staging 上的真实回答(产品负责人截图或贴文字即可)。
## 5. 改法选项(交产品负责人拍板)
### 报告
- **R1(推荐):报告前面加一段模型写的「解读」**,按竞品的章节:总评、性格、事业、财富、感情、健康、现在这几年(当前大运与接下来两个子运)、几条具体建议。
- 素材只用引擎已算好的事实(同对话的同源卡),不新增算法。
- 写法照第 3 节 1~5,但守我方红线:不写病名、不给投资指令、不写「注定 / 先苦后甜」;免责每章最多一句,不逐句。
- 原有表格和附录整体后移,标题改为「计算依据(附录)」。
- 代价:每份报告多一次模型调用(约数十秒、有成本),要做 A/B(对 77 例里的名人盘人工读几份)。
- **R2:只改模板,不加模型。** 去掉内部口径句与字段名、免责只留章首一句、改第二人称、术语第一次出现加中文括注。确定、便宜,但仍然只是逐条说明,**写不出「几条因素合成一个人」的叙事**。
- 两者不冲突:可以 R2 先做(一两天),R1 随后。
### 对话
- **C1:保持「懂行的姐姐」口吻,吸收「盘面 → 机制 → 生活」的一句链。** 依据不再只塞括号,正文里用一句白话说出「为什么」;术语仍是中文、一段最多一个。
- **C2:向竞品靠拢,允许关键术语保留原文并带中文括注**(如「功能大吉星(Yogakaraka)」)。会更「像占星师」,但推翻 10-01 起「不出现梵文外文」的决定(BUG-1132~1134)。
- **C3:对话不动,只改报告。**
## 6. 不管选哪个都守的线
- 不写病名、诊断、投资指令、确定性的死亡 / 婚姻结局(AGENTS Part B4)。
- 候选出生时间不写成已确认。
- 报告解读与对话用同一套术语(罗睺 / 计都统一)。
@@ -0,0 +1,64 @@
# 进度 · 上升交界预检 + 校正开场限度(2026-10-27)
分支 `codex/lagna-precheck-20261027`。基线 `origin/staging` `009456d8e1db5ac2b284809c6e3c9623f5842f42`。任务书 `docs/tasks/TASK-lagna-precheck-20261027.md`。issue #112 选 A:不做 6 条断语。
## 做了什么
- L1:按出生资料算出要扫描的时间窗。医院记录、家人钟点、大概时间用前后分钟,缺了就用表单默认值。时段含跨午夜。不知道时间则当天 00:00–23:59。已采用或已确认的校正时间、旧资料导入,不显示。超过 1441 分钟就截断。
- L2:星盘请求旁边同时问现有的上升分段接口,只算本命,3 秒超时。失败就不上这一句,星盘仍是成功。
- L3:出生资料下面一行小字。上升已经确定时没有链接。时段把「前后约 N 分钟」整句换成「按你给的时间段(开始–结束)」,不套两层。
- L4:校正开场固定句和给模型的说明都加上限度。模型没写「不保证 / 精确到某一分钟」和「不准」时,换回固定句。
## 命令
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 类型 | `frontend\node_modules\.bin\tsc --noEmit -p frontend` | 退出码 0 |
| 规范 | `frontend` 下 `npm run lint` | 0 error,122 warning(原有,本轮没有新增 error) |
| 时间窗与句子 | `node node_modules/tsx/dist/cli.mjs --test tests/lagna-precheck.test.ts` | 2 pass |
| 分段映射与失败不挡星盘 | 同上 `tests/lagna-precheck-chart.test.ts` | 3 pass |
| 页头四种文案 | 同上 `tests/chart-page-view.test.tsx` | 该文件与同批 67 条 pass,0 fail |
| 开场文案 | `rectification-opening-plain-20260926.test.ts`、`.tsx`、`rectification-nearest-boundary-opening-20261012.test.ts`、`agent-voice-copy-contract.test.ts`、`rectification-spoken-collect.test.ts`、`chat-session-url.test.ts` | pass,0 fail |
| 校正代理 | `tests/rectification-v9-agent.test.ts` | 37 pass,1 fail |
| 星盘路由 | `tests/chart-view-route.test.ts` | 与上一条同批,路由用例 pass |
| 全量 `npm test` | 未跑 | Windows 执行约定不跑全量,Claude 复验 |
| `next build` | 未跑 | 同上 |
| Python 快速门 | 未跑 | 本单不改 Python |
| `test:db` | 未跑 | 没动表,也没有用 Docker |
`rectification-v9-agent.test.ts` 的那一条失败是技能目录路径:`endsWith("skills/jyotish-birth-time-rectification/versions/10.0.33")`。Windows 路径用反斜杠,对不上正斜杠。本轮没有改技能包,也没有改这条断言。同文件里开场简报那条是通过的。
## 断言三栏
- 开场句数上限:原值最多 3 句;新值最多 5 句;原因是限度占两句,交界说明仍夹在目标和做法中间(BUG-1445)。
- 无窗口开场、产品开场的整句:原值两句;新值在原两句后加限度两句;原因同上。
- 产品开场句数:原值 2;新值 4;原因同上。
- 交界说明在场时的句数:原值 3;新值 5;原因同上。
- 开场简报:原值「正文两句大白话」「放在这两句之间」;新值「正文三层大白话」「放在前两句之间」,并要求保留「不保证」和「不准」;原因同上。
## 偏离
- 人物档案里的人不能进入「他自己的」校正。现有校正只读本人资料,任务书也不许改表。点链接后回到首页,沿用原来的提示「生时校正暂时只支持本人。」本人仍走现有的打开校正入口。
- 已采用(accepted)和已确认(confirmed)都不显示这一句。候选时间仍显示。
- 顶栏在这一句出现时会高于原来的 46px,没有这一句时仍是 46px。见 `frontend/DESIGN.md`。
- Skill 文件没有改,版本不升。模型说明改在页面用的系统提示里;模型漏写限度时仍换回固定句。
## 第 1 次打回(修复单 TASK-lagna-precheck-fix-20261027)
开工前 `git merge origin/staging`(当时 staging `efede95bf`)。同一分支继续。
- 星盘页的「出生时间校正」改走首页那条路:已经有没做完的校正就回到那一次,没有才新建。不再走「新开一次」,所以不会再报「仍有未完成的校正」。重新开始的按钮没动。
- 人物档案里别人的星盘:上升会换或不知道时间时,句子停在换座时刻或「上升星座定不下来。」,没有链接,也不写去做校正。本人不变。
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 类型 | `frontend\node_modules\.bin\tsc --noEmit -p frontend` | 退出码 0 |
| 规范 | `frontend` 下 `npm run lint` | 0 error,122 warning(原有,没有新增 error) |
| 时间窗、页头、链接 | `tests/lagna-precheck.test.ts`、`tests/lagna-precheck-chart.test.ts`、`tests/lagna-precheck-rectify-entry.test.tsx`、`tests/chart-page-view.test.tsx`、`tests/chat-session-url.test.ts` | 56 pass,0 fail |
| 校正开场三份和入口合同 | `rectification-opening-plain-20260926.test.ts`、同名 `.tsx`、`rectification-nearest-boundary-opening-20261012.test.ts`,加上表面合同四份 | 70 pass,0 fail |
| 全量 `npm test`、`next build` | 未跑 | 留给验收 |
| Python 快速门、`test:db` | 未跑 | 没改 Python,没改表 |
既有断言的通过值没有改。新增的是别人星盘没有链接,以及 `?rectify=1` 走 homepage。
BUG-1446、BUG-1447。真人清单第 5、6 条已按这次改法重写。
@@ -2,7 +2,7 @@
分支 `codex/ui-kit-onboarding-fix-20261026`。只推这个分支。验收通过前不合进测试环境。承载 issue #111。BUG 从 1444 起。
## U1 · 桌面加载不再把整页卸掉再挂上(BUG-1444)
## U1 · 桌面加载不再把整页卸掉再挂上(BUG-1448)
侧栏和主区始终在各自的容器里。拖宽用侧栏里的把手,宽 200–360,默认 288,拖到比 200 更窄收成 64。本命盘加在对话列旁边,不把对话列挪进后到达的分栏里。
@@ -14,7 +14,7 @@
全量 `npm test`、`npm run build`、`npm run test:db`、Python 快速门留到本单全部改完再跑。
## U2 · 中英切换能看出选中(BUG-1445)
## U2 · 中英切换能看出选中(BUG-1449)
报告语言、导出语言、合盘语言,以及导出的「整篇 / 自选」,选中项改认页签自己的标记。边框和文字用主题色,背景保持中性。
@@ -24,7 +24,7 @@
断言三栏(`report-buttons-scope-20260928.test.ts`):原值选中规则只认 `aria-checked="true"`。新值认 `data-active` 或 `aria-selected="true"`。原因是页签不设 `aria-checked`,旧规则对不上。
## U3 · 没有待出提示时不再扫整页(BUG-1446)
## U3 · 没有待出提示时不再扫整页(BUG-1450)
提示都看过、清单已关、或当前没有能出的提示时,不挂监听。回答正在生成时不扫描。需要时只盯锚点旁边的容器。
@@ -32,7 +32,7 @@
| --- | --- | --- |
| 提示监听 | `node node_modules/tsx/dist/cli.mjs --test tests/onboarding-hint-observer.test.tsx tests/onboarding-checklist-20261022.test.ts` | 14 通过,0 失败,退出码 0 |
## U4 · 启程动效只在启程里播(BUG-1447)
## U4 · 启程动效只在启程里播(BUG-1451)
清单已关不播。还在启程里才播。动画代码没到手或超过 300 毫秒,内容保持可见。
@@ -40,7 +40,7 @@
| --- | --- | --- |
| 动效范围 | `node node_modules/tsx/dist/cli.mjs --test tests/onboarding-motion-gate.test.tsx tests/onboarding-motion-20261022.test.ts tests/onboarding-hint-observer.test.tsx` | 10 通过,0 失败,退出码 0 |
## U5 · 清单关掉不翻报告,完成后会打勾(BUG-1448)
## U5 · 清单关掉不翻报告,完成后会打勾(BUG-1452)
清单已关时只读「是否关掉」。还开着时,报告和合盘改成一次「有没有」。加人、合盘存上或报告完成后,这三项再读一次,不用整页刷新。进站时已经做完、但没有关掉的账户,仍会发这一次「有没有」,因为关闭时间这时不写;不再按人和页翻。
@@ -48,7 +48,7 @@
| --- | --- | --- |
| 拉取与打勾 | `node node_modules/tsx/dist/cli.mjs --test tests/onboarding-facts-refresh.test.tsx` | 4 通过,0 失败,退出码 0 |
## U6 / U7 · 拖动排序一次写完,新对话仍在上面(BUG-1449)
## U6 / U7 · 拖动排序一次写完,新对话仍在上面(BUG-1453)
会话和档案的排序各改成一个请求。数据库在一次事务里写完整组,任何一行不属于当前用户就整组不动。没拖过的对话按最近活跃排在上面,拖过的排在下面。
@@ -59,7 +59,7 @@
断言三栏(`database-local-business.test.ts` 排序段):原值只核对两列存在,以及 authenticated 能更新 `archive_order`。新值多核对整组顺序的迁移已应用、不在 `frontend/db/migrations`,以及两个函数只给 authenticated 执行。原因是 U6 要一次事务写完整组,列的语义不改。
## U9 · 类名只用一份,验证码输入钉住版本(BUG-1450)
## U9 · 类名只用一份,验证码输入钉住版本(BUG-1454)
组件改回原来的类名函数。验证码输入钉在 1.5.0。锁文件里 150 个包的地址改回官方源。命令行工具自带的旧类名包还在,页面不引用。
+2
View File
@@ -536,3 +536,5 @@
| `TASK-full-data-parity-1-fix-20261022.md` | `PROGRESS-full-data-parity-1-fix-20261022.md` | **#91 A 段第 1 次打回**:新六章 69 节里 16 节在三张虚构盘上整节「未判定」,其中 12 节数据在资料包里、是读错了字段;测试抓不到整节未判定;新六章绕过了报告口径替换;中文附录悄悄丢列和瑜伽条目要量出来 | 已合入 staging | `codex/full-data-parity-1-20261021` |
| `TASK-full-data-parity-1-b-fix-20261023.md` | `PROGRESS-full-data-parity-1-b-20261023.md` | **#91 B 段修复**:K1–K3 已交;K4 年运键序与 Yogini 子运字段已补(BUG-1425、BUG-1426) | 已合入 staging | `codex/full-data-parity-1-20261021` |
| — | `PROGRESS-full-data-parity-1-fix2-20261022.md` | **#91 A 段第 2 次打回**(Claude 口头修复单 F1~F4):11 节只印「未判定」和键名改读真实记录;测试只认非第一列真实值、禁止键名格;中文瑜伽组合句由中文源给出(BUG-1418);六章降为 `##`、节 `###`(BUG-1419) | 本地完成,待验收 | `codex/full-data-parity-1-fix2-20261022` |
| `TASK-lagna-precheck-20261027.md` | — | **#112 选 A**:星盘页页头告诉用户上升在其时间精度内会不会换(复用现成的 D1 窗口扫描,纯计算);校正开场说清能做 / 不能做(BUG-1444、BUG-1445) | 待执行 | `codex/lagna-precheck-20261027` |
| `TASK-lagna-precheck-fix-20261027.md` | — | **#112 第 1 次打回**:已有进行中的校正时点链接报冲突(应走首页续上);别人的星盘页不该给校正链接 | 待执行 | `codex/lagna-precheck-20261027` |
+140
View File
@@ -0,0 +1,140 @@
# 任务书:上升交界预检 + 校正开场说清限度(issue #112,2026-10-27)
- 执行方:Grok。分支 `codex/lagna-precheck-20261027`,worktree `.worktrees/lagna-precheck-20261027`。
- 来源:`docs/research/competitor_past_event_check_2026_10_27.md`(竞品「推断前事」调研);产品负责人 10-27 在 #112 选 **A**。
## 基线
- `origin/staging` = `6df8d1578`(开工时以实测为准)。
- 同期在途:#111(组件库与新手引导修复单,分支 `codex/ui-kit-onboarding-fix-20261026`)改 `ShellFrame`、`globals.css` 等。本单只碰星盘页页头一行与校正开场文案,**不改 `ShellFrame` / `globals.css` 的既有规则**;交回前 `git merge origin/staging`,若 #111 已合入,以合入后的为准解冲突。
## 1. 现状实证(按符号定位)
### 1.1 用户已经告诉我们「时间有多准」
- 资料表与人物档案都存了精度:`birth_time_source`(`hospital_record` / `family_exact` / `approximate` / `period_only` / `unknown` / `legacy_import`)、`uncertainty_before_minutes` / `uncertainty_after_minutes`、`declared_window_start` / `declared_window_end`、`birth_time_status`(迁移 `20260717020000_birth_time_journey.sql`、`20260822010000_declared_birth_window_clocks.sql`、`20260925020000_chart_subject_typed_columns.sql`)。
- 表单:`frontend/src/components/birth-time-intake.tsx` 的 `BirthTimeIntakeFields`;选项在 `frontend/src/lib/birth-time-intake-model.ts`:`approximateUncertaintyOptions`(15 / 30 / 60 / 120 分钟),`birthTimeSourceDefaults.hospital_record` 前后各 2 分钟;时段窗口由 `declaredWindowRangeForDraft` 给出。
- 表单里对医院记录写着「系统会无感检查前后 2 分钟的上升与 D9 / D10 稳定性」——**但星盘页从来没把检查结果告诉用户**。
### 1.2 「整窗只有一个上升」已经能算,而且很快
- `scripts/rectification_varga_segments_api.py::scan_varga_segments`,接口 `POST /api/rectification/v5/varga-segments`,传 `target_charts: ["D1"]` 返回 `segments.D1`(每段起止与星座号)和 `full_window_unique.D1`,自带磁盘缓存;岁差走 `_segment_ayanamsa`(BUG-1309)。
- Claude 本机实测(Linux,虚构地点,冷缓存,只算 D1):前后 15 分钟 31 分钟 **0.02 秒**;前后 2 小时 241 分钟 **0.09 秒**;整天 1441 分钟 **0.54 秒**。所以可以和星盘一起算、一起揭幕,不需要单独等待。
- 目前只有生时校正调用它:`frontend/src/lib/rectification-agentic/opening-boundary.ts::fetchOpeningBoundary`、`v9/segment-scan.ts::scanCaseSegments`。
### 1.3 星盘页
- `frontend/src/components/chart-page/chart-page-view.tsx::ChartPageView`:页头 `birthline`(日期 / 时间 / 地点 + 铅笔)作为 `note` 传给 `SecondaryPageShell`;上升只出现在 Vedic 表格那一行(`chart-vedic-tab.tsx`,`label="上升"`)。
- 取数:`useChartPage` → `fetchChartView` → `GET /api/chart-view` → `frontend/src/lib/chart-view-service.ts::loadChartView`(`loadSubjectBirth` 拿到出生资料后 `postEngine` 调 Python `POST /api/chart`)。
### 1.4 校正开场
- 固定句:`frontend/src/lib/rectification-agentic/user-copy.ts::openingSpokenBody`(「我们来把你的出生时间缩小到更准的范围……做法很简单:你说几件人生里的大事和大概年月,我拿去和星盘对照。」)与 `openingBoundarySentence`;模型写的开场由 `isAcceptableOpeningBody` 把关,不合格就换成固定句(`v9/agent-run-attempt.ts`)。
- 模型开场提示:`v9/agent-run-messages.ts` 的开场简报段;口吻在 `frontend/src/mastra/agentic-rectification.ts`(BUG-1257)。
- 开场**没有说**这一步做不到什么、答「不准」会怎样、可以随时停。
## 2. 根因
1. 「上升在你给的精度内会不会换」这件事我们早就会算,但只在用户走进生时校正之后才用;星盘页对 64/77(±10 分钟,v5 评价集)根本不用问的人什么也没说,对上升会换的人也没提醒。
2. 校正开场只讲「怎么做」,不讲「能做到什么程度」;竞品把限度写在最前面,读起来更可信。
## 3. 决策记录(产品负责人 10-27,#112 选 A)
1. **不做**竞品那种「6 条断语 + 吻合分」,也不新增任何提问。
2. 上升交界预检:纯计算,不调模型,不扣点。
3. 校正开场按竞品的诚实口径改写:能做什么、不能做什么、答「不准」就记不准、可以随时停下照原时间用。
4. 显示位置:**星盘页页头**(本人和人物档案里每个人的星盘页)。首页今天没有任何出生资料展示位,本单不在首页新增;要加另立单。
5. 「上升确定」**只说上升**,不说「不用校正」——09-30 研究(`rectification_varga_resolution_2026_09_30.md`)证明「不用校正」只对上升成立,九分盘 / 十分盘 0/77。
## 4. 硬红线
1. 不改数据库结构,不加迁移。
2. `scripts/jyotish_api_server.py` 不加方法、不加路由(复用现有 `varga-segments` 接口);`frontend/src/app/(app)/page.tsx` 不动。
3. 不调模型,不加新问题,不改校正打分、候选、冻结文件(`references/rectification_sealed_holdout.v1.json` 等)。
4. 一次揭幕:这一行和星盘一起出现;算不出来(超时、接口错、资料不全)就**整行不显示**,不出 spinner、骨架或「正在检查」。预检失败不得让星盘页失败。
5. 文案对照 `frontend/docs/VOICE.md`:不用「分盘」「候选」「区间」「Lagna」「D1」等词;星座用中文名。
6. 改 UI 同提交更新 `frontend/DESIGN.md`;首屏 gzip ±2%(本单不碰首页,预期不变)。
7. 改既有断言写「原值 / 新值 / 原因」三栏(AGENTS §7.3、§7.8)。下列测试按文本断言开场文案,必须同轮改:`rectification-opening-plain-20260926.test.ts(x)`、`rectification-nearest-boundary-opening-20261012.test.ts`、`rectification-v9-agent.test.ts`、`agent-voice-copy-contract.test.ts`;另 grep `openingSpokenBody` / `isAcceptableOpeningBody` 的其余引用。
8. 隐私:测试只用虚构盘。
## 5. 任务分解(一条一个提交)
### L1 · 精度窗口(前端纯函数)
新增 `frontend/src/lib/lagna-precheck.ts`(名字可调):
- 输入:出生资料(同 `loadSubjectBirth` 返回的形状)。输出:`{ start_at, end_at, minutes } | null`。
- 规则:
- `hospital_record`、`family_exact`、`approximate`:报告时间 −`uncertainty_before_minutes` 到 +`uncertainty_after_minutes`(缺值按 `birthTimeSourceDefaults`)。
- `period_only`:`declared_window_start`–`declared_window_end`(跨午夜照 `declaredWindowRangeForDraft` 的口径)。
- `unknown`:当天 00:00–23:59。
- `birth_time_status` 为已确认(采用了校正结果)或 `legacy_import`:返回 `null`(不显示这一行)。
- 窗口超过 1441 分钟时截到 1441(接口上限)。
- 验收:单测覆盖以上每种来源,含跨午夜时段、缺失不确定度时用默认值。
### L2 · 星盘页拿到结果(与星盘同一次请求)
- `loadChartView` 在拿到出生资料后,与 `/api/chart` **并行**调用 `/api/rectification/v5/varga-segments`(`target_charts: ["D1"]`,岁差跟这张星盘当前的岁差设置一致,经纬度与时区同星盘)。单独超时 3 秒;失败就不带这段。
- `ChartViewResponse` 加一个可选字段(例如 `lagnaPrecheck: { state: "fixed" | "may_change" | "unknown_time"; signs: string[]; changeAt?: string[]; windowMinutes }`),映射在 `chart-view-mapper.ts`;没有就不显示。
- 只有本人或人物档案里有权看这张盘的人能拿到(沿用 `loadChartView` 现有鉴权,不新开路由)。
- 验收:单测——接口返回单段 → `fixed`;两段 → `may_change` 且带换座时刻;接口抛错 / 超时 → 字段缺省、星盘照常 200。
### L3 · 页头一行文案
在 `ChartPageView` 页头 `birthline` 下面加一行小字(样式同页头说明文字,不加卡片、不加图标),文案:
| 情况 | 文案 |
| --- | --- |
| 窗口内上升不换 | 按你给的时间精度(前后约 N 分钟),上升星座都是{X}座,这一点不会因为时间误差而变。 |
| 窗口内会换(两个星座) | 按你给的时间精度,上升可能是{X}座,也可能是{Y}座(大约 {HH:MM} 换座)。想定下来可以做一次出生时间校正。 |
| 会换(三个及以上) | 按你给的时间段,上升可能落在{X}座、{Y}座、{Z}座中的一个。想定下来可以做一次出生时间校正。 |
| 不知道出生时间 | 不知道出生时间时,上升星座定不下来;做一次出生时间校正可以缩小范围。 |
- 「出生时间校正」做成链接,进入现有的校正入口(复用现有入口的路由与参数,人物档案里的人进入他自己的校正);**确定**那一行没有链接。
- 时段窗口(`period_only`)把「前后约 N 分钟」换成「按你给的时间段({开始}–{结束})」。
- 英文界面若星盘页有英文版,照同样四句给英文;没有就只做中文。
- 验收:组件测试四种情况各一条;`fixed` 没有校正链接;字段缺省时 DOM 里没有这一行。`frontend/DESIGN.md` 记一句这行的位置与样式。
### L4 · 校正开场说清限度
改 `openingSpokenBody`(固定句)并同步模型开场简报(`agent-run-messages.ts`),开场正文改成三层意思,口吻按 BUG-1257 的姐姐口吻:
1. 做什么:「我们来把你的出生时间缩小到更准的范围,现在先在 {窗口} 之间找。」(保留现有 `productDelivery` 分支的说法)
2. 怎么做:「你说几件人生里的大事和大概年月,我拿去和星盘对照。」
3. **限度(新增)**:「这一步能帮你把用来解读的星盘定下来,但不保证精确到某一分钟;对不上的地方你直接说不准,我会照实记下,不会换个说法圆回来。中途想停也可以,照你原来填的时间用。」
- `openingBoundarySentence` 保留,位置在 1 和 2 之间不变。
- `isAcceptableOpeningBody`:模型写的开场必须含限度这层意思(以「不保证」或「精确到某一分钟」与「不准」两处为判据),否则回落固定句;`OPENING_BODY_JARGON` 不放宽。
- 验收:上面第 4 节第 7 条列的测试按三栏改完并通过;新增一条:模型开场缺限度句 → 回落固定句。
## 6. 验收分工
| 项 | 谁 |
| --- | --- |
| `tsc --noEmit` 0 错、`npm run lint` 0 error、`npm test` 全量与 staging 基线逐条一致 | Grok 跑,Claude 复验 |
| `next build` 后 `/` 仍 Static,首屏 gzip ±2% | Grok 跑,Claude 复验 |
| Python:本单不改 Python;若碰了 `scripts/**` 或 `tests/**`,跑快速门全量 | Grok |
| 浏览器真机:本人星盘页(医院记录 / 大概时间 / 时段三种资料各一次)、人物档案里一个人、点链接进校正、校正开场读一遍 | 产品负责人(写进 `docs/testing/lagna-precheck-20261027.md`) |
## 7. 让步顺序
时间不够时先保 L4(开场文案),再 L1→L2→L3;L3 的三个及以上星座那一句可以并进「会换」一句(列出所有星座)。不得为赶工跳过「失败就不显示」。
## 8. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/lagna-precheck-20261027 .worktrees/lagna-precheck-20261027 origin/staging
cd .worktrees/lagna-precheck-20261027/frontend && npm ci
./node_modules/.bin/tsc --noEmit && npm run lint && npm test # 记下基线失败清单
grep -rn "openingSpokenBody\|isAcceptableOpeningBody\|openingBoundarySentence" tests/ src/ | grep -v node_modules
```
## 9. BUG 编号
开工时 `grep -o 'BUG-[0-9]*' docs/BUG_HISTORY.md | sort -u -V | tail -1`;当前最大 BUG-1443,本单从 **BUG-1444** 起:
- BUG-1444:星盘页不告诉用户上升在其时间精度内是否会换(预检能力早已存在只给校正用)。
- BUG-1445:校正开场不讲限度。
交付:只推分支,在 #112 回报 SHA,标签改「待验收」。
@@ -0,0 +1,38 @@
# 修复单:上升交界预检(issue #112,第 1 次打回,2026-10-27)
- 被验提交:`903d206f3`(分支 `codex/lagna-precheck-20261027`)
- 原任务书:`TASK-lagna-precheck-20261027.md`
- 执行方:Grok。同一分支继续,开工前 `git merge origin/staging`(不 rebase)。BUG 编号开工时核对最大号 +1(#111 的分支也在用 1444 起的号,以合入 staging 时的实际最大号为准,撞号由合并方改)。
## 验收结论(Claude,Linux)
| 项 | 结果 |
| --- | --- |
| `tsc --noEmit` | 0 错(换新 `.next` 后) |
| `npm run lint` | 0 error |
| `npm test` 全量 | 5183 项,失败 25,与 staging 已知名单逐条相同;Windows 上那条技能路径失败在 Linux 通过 |
| `next build` | `/` 仍 Static;首屏 gzip 727,726,staging 727,249,+0.07% |
| Python 快速门 | 通过 |
| 文案、窗口、失败不挡星盘、开场限度、断言三栏 | 都对 |
未通过两条,都在「出生时间校正」这个链接上。
## F1 · 已有进行中的校正时,点链接会报错(必修)
`use-rectification-surface.ts` 里 `?rectify=1` 调的是 `startNewRectification` → `openRectificationCase("new", …)`。数据库函数 `open_agentic_rectification_case_v2` 在 `p_intent = 'new'` 且有可续的进行中校正时**直接抛 `agentic_rectification_active_case_conflict`**(`20260812010000_agentic_rectification_v9_runtime.sql`,「restarting with an active case must surface a safe conflict」)。上升会换的人恰恰最可能已经开过一次校正,他们点链接看到的是报错,而不是回到自己那次校正。
修法:链接走首页入口的同一路径——`openRectificationCase("homepage", null, null)`(有进行中的就续上,没有就新建;即本文件里现成的那个 homepage 打开函数)。不要新建 intent,不改数据库。
验收:加一条测试——已有可续校正时,`?rectify=1` 走 `homepage` 意图、不出现冲突提示;没有时新建。
## F2 · 别人的星盘页不要给链接(必修)
现在人物档案里别人的星盘页也显示「出生时间校正」链接,点进去只得到「生时校正暂时只支持本人。」——一个点了没用的入口(产品口径:多余入口宁可删除)。
修法:`subjectId` 不是本人时,`lagnaPrecheckLine` 的「会换」「不知道时间」两种情况**不带链接、也不写「想定下来可以做一次出生时间校正」那半句**,句子止于「(大约 HH:MM 换座)。」或「上升星座定不下来。」;本人不变。
验收:组件测试——非本人两种情况 DOM 里没有链接、没有「出生时间校正」字样;本人照旧有。
## 交回前必跑
`tests/lagna-precheck*.test.ts`、`tests/chart-page-view.test.tsx`、`tests/chat-session-url.test.ts`、校正开场三份测试;全量与构建由 Claude 复验。
@@ -114,3 +114,22 @@
- `npm run test:db`(U6、U7 改了表的读写路径)。
- Python 快速门 `run_quality_gate.py --profile quick`。
- `docs/testing/ui-kit-migration-20261023.md`、`onboarding-journey-20261022.md` 补上本单的真机步骤(桌面加载不闪、中英切换能看出选中、老用户无启程动画)。
## 第 2 轮验收(2026-10-27,被验 `365a623fc`;同一单第 2 次未过,按规则交产品负责人决定由谁修)
验收数字(Claude,Linux):`tsc` 0 错;lint 0 error;`npm test` 5196 项、失败 25,与 staging 已知名单逐条相同(比 staging 多 20 项测试);`/` 仍 Static;首屏 gzip 694,941(基线 `0f66d92d4` 646,201,+7.54%;当前 staging 727,249,−4.4%);`test:db` 83 项过 81,2 条为本机环境已知;Python 快速门通过。U2、U3、U4、U6、U7、U9 通过。
还要修的(按严重度):
1. **揭幕后整页回到「正在载入账户」**(违反 AGENTS §6「揭幕后不得出现加载」,也是 U1 同类的整页卸载)。`page.tsx` 的加载判断新加了 `account && !subjectCatalogReady`;而 `use-profile-onboarding.ts` 两处(为别人建档补地点后、`chooseOnboardingOther`)调用 `invalidateSubjectCatalog()` 把 `catalogReady` 置回 false,于是整页聊天被换成加载屏;那次重载失败时 `useCurrentSubjectReady` 只在挂载时重试,页面会一直停在加载屏。修法:只有**首次**未就绪才走加载屏(已揭幕过就保留旧名单直到新名单到),重载失败要能恢复。加测试:揭幕后调用 `invalidateSubjectCatalog()` 不出现 `app-loading`。
2. **对话右栏盘面拖不动宽度**(读代码判断,未在浏览器复现)。`chat-chart-split.tsx` 的 `ResizablePanelGroup` 里只剩一个面板加固定 `style={{ width }}`,把手两边没有可交换的面板,`onWidth` / 拖到最小收起都不会触发。修法:让聊天列仍是组里的另一个面板,但**不随右栏加载换位**(U1 的要求),或改用不依赖分组的拖宽把手;加一条测试证明拖动会调用 `onWidth`。
3. **侧栏拖宽把手没有键盘操作**:原组件的左右方向键没了。补回方向键调整宽度。
4. **测试删减没写三栏**(AGENTS §7.3):`report-export-drawer.test.tsx` 删了「关闭导出」按钮那条;`chart-type-picker.test.tsx` 删了 `doesNotMatch(source, /<dialog|<button|ToggleGroup|role="tablist"/)`;`birth-time-guided-review-fixes.test.ts` 整条删除(组件删了可以删,但要写原值 / 新值 / 原因)。补回或补三栏。
5. **为了让测试能跑改了线上登录代码**:`modules/identity/client.ts` 加 `customFetchImpl: globalThis.fetch`、`email-otp-login.tsx` 加 `NextImage.default` 兼容。这两处碰真实登录路径且不在任务书里;改回去,把替身放在测试里。
6. 启程清单入口改成延后加载后,揭幕后才冒出来(第二次变化)。给它预留位置,或与首屏一起出现。
7. 小:删掉的旧校正画面在 `globals.css` 和 `birth-time-choice.css` 里留下的无用样式,确认无引用后删除。
需要产品负责人定的:
- **首屏 +7.54%**:多出来的是组件库外壳与整站样式,延后加载已经做了。是接受(写进 BLOCKED / DESIGN 的体积说明),还是继续压到 ±2%?
- **U11 第 2、3 项**(月亮开场、给别人看时天空过场的上升句):执行方说现有资料里没有这两个值、本单又不许新增请求,所以没做。是放弃,还是允许为此多读一次已算好的盘?
+12
View File
@@ -0,0 +1,12 @@
# 真机清单 · 上升交界预检与校正开场(issue #112)
部署到测试站之后再看。这里没有登录浏览器,不能代替下面的走查。
本人星盘页各看一次(电脑、手机都行):
1. 医院记录(前后大约 2 分钟):出生资料下面有一句。上升不换时,句子里没有「出生时间校正」。会换时,句子里有这个链接。
2. 大概时间(前后 15 分钟或你选过的范围):同样看这一句是否和你填的精度一致。
3. 只知道一个时段:句子改成「按你给的时间段(开始–结束)」,不再写「前后约 N 分钟」。
4. 已经采用过校正时间的盘:这一句不出现。
5. 人物档案里另一个人的星盘页:这一句可以出现。上升会换或不知道时间时,句子里没有「出生时间校正」,也没有可点的链接。不会给他另开一套校正。
6. 本人点「出生时间校正」:如果已经有一次没做完的校正,回到那一次,不要出现「仍有未完成的校正」。如果还没有,新开一次。开场要能听到三层意思:在哪段时间里找、你说几件大事和大概年月、不保证精确到某一分钟,说不准就照实记,中途可以停。