Files
Jyotisha/docs/tasks/TASK-rectification-explicit-entry-20261012.md
T

9.5 KiB
Raw Blame History

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. 根因

  1. 入口完全依赖模型判断,规则写成「推得不准」场景,没覆盖「用户直接要做校正」。
  2. 服务端拒绝时有两种原因被设计成静默。
  3. 普通对话模型没有「不能在对话里做校正」的边界,于是自己收经历、承诺收窄。用户照做也不会进入校正引擎计分。
  4. 首轮强制排盘合同没有给「要校正」这轮留出口。

3. 决策记录(产品 2026-10-12)

  1. 用户明确要求做生时校正时,直接进入校正:不先写解读,不用点卡。是否「明确要求」由模型判断,禁止正则 / 关键词(BUG-976/977 口径不变)。
  2. 推翻 BUG-1248 的两条:
    • 「工具只记录提议、进入要点卡」:对用户明确要求的这一轮,改为直接打开。「推得不准、可能是时间问题」时主动提议仍走卡片,不变。
    • product_disabled、pricing_unavailable「正文不要提校正」:改为必须用一句话说明现在做不了,不得静默。措辞对照 frontend/docs/VOICE.md,不写价格、不写内部原因名。
  3. 普通对话模型不得承诺「能收窄出生时间」,不得在对话里收集经历假装校正;用户要做校正,就走第 1 条。
  4. 申报时段下不得写大运、子运的精确起止(守 declaredWindowInstruction 原有规定)。只补指令与回归测试,不改证据卡。
  5. 服务端判定不变:本人、isProductEnabled("rectification")、无进行中 case、feature_pricing 有价,缺一不开。家人档案、已有进行中 case 照原口径一句话说明(进行中的 case 可给「接着做」入口,见 T3)。

4. 硬红线

  1. 不用正则 / 关键词判断意图,不新增前端意图判断。
  2. 不改数据库结构、不动迁移;不改校正引擎、打分、decision_policy、闸门。
  3. 守 AGENTS §6:scripts/jyotish_api_server.py 类方法数不增长;frontend/src/app/(app)/page.tsx 的 Home() 中 useState / useRef 数不增长(新逻辑进 hook / lib)。
  4. 不在任何文件、测试、日志里写真实用户资料;实测只用公开名人 golden 盘或虚构资料。
  5. 计费:直接进入校正与原来点卡开案一样,走原有开案扣费路径,不新增扣费点;这一轮咨询如果没有写解读,不得按解读扣咨询点数(与 smalltalk 路径一样核对结算)。
  6. 测试总数不得低于基线;改既有断言写「原值 / 新值 / 原因」三栏。

5. 任务分解

T0 取证(先做,做不到写成环境缺口)

  • 目标:确认 10-11 那一轮模型是否调用了 offer-birth-time-rectification,服务端返回了什么。
  • 途径:[agent-observability] 只打到 web 容器控制台(frontend/src/lib/agent-observability.ts consoleSink)。需要 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。