Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwMNZEzdzmrbPhuRNmZe3C
9.5 KiB
9.5 KiB
TASK · 对话里明说要校正就直接进入生时校正(BUG-1306,2026-10-12)
- 基线:
origin/staging@fddddaab(已部署代码de4cfeb8,含 BUG-1247~1251「校正并入对话」第一步)。 - 分支 / worktree:
codex/rectification-explicit-entry-20261012/.worktrees/rectification-explicit-entry-20261012 - 串行顺序:本单最先做。
TASK-rectification-nearest-boundary-opening-20261012若改到frontend/src/app/(app)/page.tsx、use-rectification-surface.ts或校正开场组件,必须等本单合入 staging 后再开工;TASK-rectification-d12-parent-probes-research-20261012是纯研究,可并行。 - BUG 编号:本单修 BUG-1306(已存在,状态 investigating)。实现中另发现的问题从开工时
docs/BUG_HISTORY.md最大号顺延(写作时最大为 BUG-1308)。
1. 事故实证
产品 10-11 在 staging 新对话第一句输入「请你帮我进行生时纠正」(本人档案,申报出生时段)。回复显示「已完成 3 步」,正文:
- 「收窄出生时间这件事能做……对得上,区间就能往里收」,要用户报有年月的经历;
- 全文没有提卡片,界面上也没有提议卡;
- 按「代表分钟」写出大运、子运的起止年月。
代码事实(行号按符号定位):
| 位置 | 事实 |
|---|---|
frontend/src/lib/consultation-thinking-plan.ts RECTIFICATION_OFFER_RULE |
规则以「用户说你推得不准时」开头;「明确想核对出生时间」只是其中一支 |
frontend/src/mastra/consultation-tools.ts createRectificationOfferTool |
工具只记录提议,进入校正要用户再点卡 |
同文件 RECTIFICATION_OFFER_REFUSAL_NOTES |
product_disabled、pricing_unavailable 要求「正文不要提校正」 → 用户看到的是没回应 |
frontend/src/app/api/consult/route.ts declaredWindowInstruction |
已写「精确应期一律不可用」,模型仍写了子运起止 |
| 同文件 natal / window 两处「运行合同不完整」重试 | 首轮没调计算工具就强制重跑 → 「要校正」这一轮也会被逼着先排盘写解读 |
| BUG-1247 | 删除首页入口与文字口令后,新用户进校正只剩「模型调工具 → 服务端放行 → 出卡 → 点卡」一条路 |
| BUG-1248 上线前模型实测 | 只测了四种说法,没有「首轮直接点名要校正」 |
2. 根因
- 入口完全依赖模型判断,规则写成「推得不准」场景,没覆盖「用户直接要做校正」。
- 服务端拒绝时有两种原因被设计成静默。
- 普通对话模型没有「不能在对话里做校正」的边界,于是自己收经历、承诺收窄。用户照做也不会进入校正引擎计分。
- 首轮强制排盘合同没有给「要校正」这轮留出口。
3. 决策记录(产品 2026-10-12)
- 用户明确要求做生时校正时,直接进入校正:不先写解读,不用点卡。是否「明确要求」由模型判断,禁止正则 / 关键词(BUG-976/977 口径不变)。
- 推翻 BUG-1248 的两条:
- 「工具只记录提议、进入要点卡」:对用户明确要求的这一轮,改为直接打开。「推得不准、可能是时间问题」时主动提议仍走卡片,不变。
product_disabled、pricing_unavailable「正文不要提校正」:改为必须用一句话说明现在做不了,不得静默。措辞对照frontend/docs/VOICE.md,不写价格、不写内部原因名。
- 普通对话模型不得承诺「能收窄出生时间」,不得在对话里收集经历假装校正;用户要做校正,就走第 1 条。
- 申报时段下不得写大运、子运的精确起止(守
declaredWindowInstruction原有规定)。只补指令与回归测试,不改证据卡。 - 服务端判定不变:本人、
isProductEnabled("rectification")、无进行中 case、feature_pricing有价,缺一不开。家人档案、已有进行中 case 照原口径一句话说明(进行中的 case 可给「接着做」入口,见 T3)。
4. 硬红线
- 不用正则 / 关键词判断意图,不新增前端意图判断。
- 不改数据库结构、不动迁移;不改校正引擎、打分、
decision_policy、闸门。 - 守 AGENTS §6:
scripts/jyotish_api_server.py类方法数不增长;frontend/src/app/(app)/page.tsx的Home()中useState/useRef数不增长(新逻辑进 hook / lib)。 - 不在任何文件、测试、日志里写真实用户资料;实测只用公开名人 golden 盘或虚构资料。
- 计费:直接进入校正与原来点卡开案一样,走原有开案扣费路径,不新增扣费点;这一轮咨询如果没有写解读,不得按解读扣咨询点数(与 smalltalk 路径一样核对结算)。
- 测试总数不得低于基线;改既有断言写「原值 / 新值 / 原因」三栏。
5. 任务分解
T0 取证(先做,做不到写成环境缺口)
- 目标:确认 10-11 那一轮模型是否调用了
offer-birth-time-rectification,服务端返回了什么。 - 途径:
[agent-observability]只打到 web 容器控制台(frontend/src/lib/agent-observability.tsconsoleSink)。需要 staging 主机docker logs(按deploy/README.md)里该时段toolCalls。另一佐证:该会话的chat_sessions.messages里有没有rectificationOffer。 - 没有主机 / 数据库访问:写进
BLOCKED.md,在进度记录给产品一条可照做的查法(只查工具名与结果,不复制正文与出生资料)。不阻塞 T1–T5。 - 验收:进度记录写明取证结果或环境缺口。
T1 直达工具语义
offer-birth-time-rectification增加「用户这一轮明确要求做校正」这一参数,或拆出一个开案工具(执行方选一种,写理由)。由模型判断,不用正则。- 服务端判定通过时,
run.completed事件(或新事件)带「直接打开」的指令和来源会话号;浏览器收到后调用现有打开流程:useRectificationSurface的打开函数,intent=homepage加sourceSessionId,复用 BUG-1249/1250 的来源绑定与「回到刚才的对话」。 - 本轮助手消息只留一句过渡(例如「好,我们开始核对出生时间。」),消息上记一条与提议卡同结构的记录(状态直接为
opened),保证刷新后来源仍能找回(findRectificationSource只认带 caseId 的提议卡)。 - 验收:单测覆盖「通过 → 直接打开且绑定来源」「同一轮不重复开案」「刷新后来源可找回」;
bindRectificationSource对opened记录幂等。
T2 首轮合同豁免
- natal 与 window 两条路径的「运行合同不完整」重试:本轮已经走直达(T1 通过)时不重试、不要求计算工具,也不写解读。
- 服务端拒绝时同样不重试,只写一句说明。
- 验收:单测断言两条路径在直达 / 拒绝时都不触发重试;正常咨询轮重试行为不变(原测试不改或三栏说明)。
T3 拒绝不静默
- 改
RECTIFICATION_OFFER_REFUSAL_NOTES:product_disabled、pricing_unavailable改为一句话说明现在做不了。case_in_progress除说明外,直达场景下直接打开那个进行中的 case(与历史里打开相同),不新开。 - 验收:四种拒绝各一条单测,断言 note 不含「不要提校正」;文案对照 VOICE.md。
T4 普通对话的边界
- 在
RECTIFICATION_OFFER_RULE(只此一处定义)里加:不承诺收窄出生时间,不在对话里收集经历做校正;用户要做就调工具。 declaredWindowInstruction补一句:大运、子运只说「在哪一段附近」,不写起止年月日。- 验收:指令内容测试;规则仍只定义一处。
T5 模型实测(公开名人 golden 盘或虚构资料,至少 deepseek-flash 与产品默认模型各一遍,每场景 ≥2 次)
| 场景 | 期望 |
|---|---|
| 首轮直接点名:「请你帮我进行生时纠正」 | 直接打开,不写解读 |
| 不同说法:「帮我校正出生时间」「想核对一下出生时间准不准」「我出生时间是估的,帮我对一下」 | 直接打开 |
| 追问轮里才提出要校正 | 直接打开 |
| 只是不认同解读:「你说我事业不顺,我觉得挺顺的」 | 不得进入,按纠正规则改读 |
| 过去的事对不上 + 时间是估的(未明确要校正) | 出提议卡(原行为) |
| 家人档案明确要校正 | 一句话说明暂不支持,不开案 |
服务端 pricing_unavailable |
一句话说明,不静默 |
| 申报时段普通咨询 | 不出现子运起止年月日、不承诺收窄 |
- 验收:进度记录逐场景给次数与结果;任一「不得进入」场景进入了即不通过。无模型凭据时写成环境缺口,并补
docs/testing/真机清单。
6. 让步顺序
时间不够时依次放弃:T5 中第二个模型 → T0 取证(写缺口)。T1–T4 不可让。
7. 开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-explicit-entry-20261012 .worktrees/rectification-explicit-entry-20261012 origin/staging
grep -oE "^## BUG-[0-9]+" docs/BUG_HISTORY.md | sort -t- -k2 -n | tail -1
前端门禁:tsc --noEmit 0 错、npm run lint 0 error、npm test 失败名单与基线逐条相同、next build 后 / Static、首屏 gzip ±2%。改 UI 同提交更新 frontend/DESIGN.md;docs/BUG_HISTORY.md 的 BUG-1306 更新为 fixed-pending-verify 并写修复与验证。真机清单写到 docs/testing/rectification-explicit-entry-20261012.md。