fix(rectification): pin the adopt card and drop casual adopt copy
Independent Staging Quality Gate / validate (push) Successful in 11m34s
Independent Staging Quality Gate / publish (push) Successful in 1m56s

The time card stayed under an earlier collect question, and the close said to just use a time for now. Keep the card on the delivery turn and present the analysis as this round's result.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-05 02:03:19 +08:00
parent 7c776bdd3a
commit 329f8a2109
22 changed files with 402 additions and 52 deletions
+32
View File
@@ -8389,3 +8389,35 @@
- 复发自:BUG-430(加载方式在无 Google Fonts 网络的镜像构建里不成立)
- 修复版本:待发布
## BUG-544 | 采用卡钉在历史采集题下,最新旁白却说从下面选
- 状态:resolved
- 首次发现:2026-09-05
- 最近更新:2026-09-05
- 影响面:`attachOfferResultToTurns``applyLiveCandidateOffer``rectification-agentic-chat``candidateOffer` 锚点
- 用户现象:最新助手说「可以从下面选一个先用着」,下面没有时间卡。往上翻,卡钉在更早的「工作上呢,还记得哪年入职…」采集题下面。
- 触发条件:公开 `can_adopt` 曾为真时,当时最新助手消息还是未答完的采集题;之后继续问了家人/核对,再出采用旁白。
- 根因:三层叠加,复发 BUG-497/499。(1) 客户端 `useEffect` 只要某条消息已有同一 `resultId` 就不再改锚点。(2) `messages.find` 取第一条 `candidateOffer`,旧采集题永远赢过后面的采用旁白。(3) GET 把 `offer_result_id` 写在最新回合上时,`mergeTurnQuestions` 在旧消息 `offer_result_id` 为空时仍保留客户端脏锚点。
- 修复:未采用时卡只挂在最新已落地、且没有未答采集/区分题的助手消息上;未答采集/选择题在场则不出卡。已采用后仍不把卡挪到核对题上。GET 水合时空的 `offer_result_id` 清掉该回合的客户端脏锚点。
- 验证:`rectification-candidate-offer-anchor.test.ts`:采集题 + 后续旁白 → 卡在旁白;只有未答采集 → 无卡;已采用后卡留在原消息。`agent-voice-copy-contract``rectification-agentic-entry``rectification-adopt-flow-20260902` 既有合同仍过。
- 防复发:未采用不得把采用卡锚在未答 `collect_spoken` / `choice` 上。不得用 `messages.find` 取第一条 offer。GET 空 `offer_result_id` 不得保留客户端脏锚点。已采用后仍不得把卡锚到最新核对题。
- 相关记录:BUG-312、BUG-497、BUG-499、BUG-545
- 复发自:BUG-497、BUG-499
- 修复版本:待发布
## BUG-545 | 单分钟采用旁白把同一时刻念两遍,并说「分不开当前候选」
- 状态:resolved
- 首次发现:2026-09-05
- 最近更新:2026-09-05
- 影响面:`nonConvergingRangeNarration``templateStopExplain``RECTIFICATION_USER_COPY.adoptCue`
- 用户现象:交付句为「剩下的题分不开当前候选。更站得住的范围是 05:15,代表分钟 05:15。这只是代表性候选,不是已确认的唯一出生分钟。可以从下面选一个先用着。」听起来像内部状态,不像对人说话。
- 触发条件:可信区间收成同一分钟,且 `stop_facts` 没有可并列的第二分钟。
- 根因:模板把「范围」和「代表分钟」无条件拼在一起;`formatClockRange``05:1505:15` 收成 `05:15` 后仍套「范围是 X,代表分钟 X」。停问原因用「当前候选」这种内部词。`adoptCue` 说「选一个」,卡片却不在这句下面(见 BUG-544)。
- 修复:区间收成单分钟时改口「眼下更站得住的是 HH:MM」,不再重复。停问改成「再问下去也分不开 A 和 B」或「再问下去也分不出更准的时间了」。`adoptCue` 改为「我按你说的经历认真分析过了,下面是这次的结果。」不得说「先用着」。边界句「不是已确认的唯一出生分钟」保留。
- 验证:`agent-voice-copy-contract` 锁单分钟句式与 `adoptCue``rectification-answer-choice` 最后一题采用旁白匹配新句式或跨分钟「代表分钟」。机器词表加入旧「当前候选 / 可以从下面选一个先用着 / 下面的时间可以先用着」。
- 防复发:单分钟区间不得把范围和代表分钟念两遍。用户可见文案不得出现「当前候选」。交付收尾不得说「先用着」。交付/采用轮仍须出现代表性分钟边界语义。
- 相关记录:BUG-544、VOICE.md
- 复发自:无
- 修复版本:待发布
@@ -0,0 +1,40 @@
# PROGRESS · 采用卡锚点与交付旁白(2026-09-05)
工作树:`.worktrees/rectification-quality-probe-dedupe-20260904`
分支:`codex/rectification-quality-probe-dedupe-20260904`
基线:`origin/staging` `7c776bdd`Inter 本地字体)。未改 `.gitea/workflows/**`、未动迁移、未升级依赖、未 bump Skill(仍 10.0.14)、未改 `page.tsx`
| 任务 | 状态 | BUG |
| --- | --- | --- |
| 采用卡跟最新旁白,采集题下不出卡 | 完成 | BUG-544 |
| 单分钟交付旁白去机器腔 | 完成 | BUG-545 |
## 编号
开工时最大号 BUG-543。本单 **BUG-544、BUG-545**。未占用预留的 BUG-542。
## 实现要点
- `attachOfferResultToTurns` / `applyLiveCandidateOffer`:未采用时跳过未答 `collect_spoken` / `choice`;卡挂在最新已落地助手消息。已采用后不挪到核对题。
- GET 水合:该回合 `offer_result_id` 为空则清掉客户端脏锚点。
- 单分钟区间:`眼下更站得住的是 HH:MM`。停问:`再问下去也分不开 A 和 B` / `再问下去也分不出更准的时间了``adoptCue``我按你说的经历认真分析过了,下面是这次的结果。`
## 断言变更
| 项 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `adoptCue` | 可以从下面选一个先用着。 / 下面的时间可以先用着。 | 我按你说的经历认真分析过了,下面是这次的结果。 | 付费校正不是随便先用着;仍不说成已确认 |
| `rectification-answer-choice` 最后一题旁白 | `/代表分钟/` | `/眼下更站得住的是\|代表分钟/` | 单分钟区间不再念「代表分钟 05:00」 |
| `site`/`agentic-entry` 卡锚点 | `messages.find` 第一条 offer | `reverse().find` + `applyLiveCandidateOffer` | 旧采集题抢锚点 |
## 测试
| 命令 | 结果 |
| --- | --- |
| `npx tsx --test tests/rectification-candidate-offer-anchor.test.ts tests/agent-voice-copy-contract.test.ts` | 15/15 |
| 上两项 + adopt-flow / adopt-narration / answer-choice / collect-stall / provisional-adopt / range-offer / agentic-entry / activity-receipt | 160/160 |
| `tsc --noEmit` | 0 错 |
| 改动文件 eslint `--quiet` | 0 error |
| `page.tsx` | 未改 |
未做浏览器真人走查。清单:`docs/testing/rectification-adopt-card-anchor-20260905.md`
+1
View File
@@ -51,6 +51,7 @@
| `TASK-rectification-collect-direction-fix-20260904.md` | `PROGRESS-rectification-collect-direction-fix-20260904.md` | dated 补采集分支插在方法轮转之前,新案例第二问被家人抢占感情/事业;`7ee7f825` CSS 与合同测试脱节挡住门禁 | 已验收通过(0be51e65),待 staging 部署核对 | `codex/rectification-collect-direction-fix-20260904`BUG-531532 |
| `TASK-rectification-post-adopt-verify-20260904.md` | `PROGRESS-rectification-post-adopt-verify-20260904.md` | 采用后核对题重复已问题;核对卡「这题跳过」等于整案停止、已采用仍念"选一个先用着"、前端"没有拿到下一个问题";采用旁白承诺的 holdout/OOS 核对与实际计划不同源(原任务书 §4 错误);家庭采集题带年份前缀自相矛盾 | 待验收 | `codex/rectification-post-adopt-verify-20260904`BUG-536539 |
| `TASK-rectification-quality-probe-dedupe-20260904.md` | `PROGRESS-rectification-quality-probe-dedupe-20260904.md` | 候选区分阶段同一道"上大学"题问两次:`pickProbe` 按种类取第一条质量探针无视 `semantic_key`(第二次答案绑到错的证据);引擎对毕业等学业 kind 也套"高考发挥"模板;同域同分组质量探针不去重 | 待验收 | `codex/rectification-quality-probe-dedupe-20260904`BUG-540541 |
| — | `PROGRESS-rectification-adopt-card-anchor-20260905.md` | 采用卡钉在历史采集题下,最新旁白没有卡;单分钟交付旁白机器腔 | 待验收 | `codex/rectification-quality-probe-dedupe-20260904`BUG-544545 |
| `TASK-api-not-configured-mislabel-20260904.md` | — | 16 处路由把数据库瞬断(部署切换窗口)兜底翻译成 503「服务尚未配置」;改为仅配置错误用该文案,其余 `service_unavailable`,收敛为共享 helper | 待执行 | `codex/api-not-configured-mislabel-20260904`BUG-542 起) |
| `TASK-rectification-ux-20260902.md` | `PROGRESS-rectification-ux-20260903.md` | 会话面空白假死与交互摩擦 | 已验收 | `d159f08e`(09-03 在新基线重做后合入,BUG-505509 |
@@ -0,0 +1,27 @@
# Staging 人肉复核 · 采用卡位置与交付旁白(2026-09-05)
给产品负责人。不要把真实案例里的年份、事件或候选分钟写进任何记录。
对应 BUG-544、BUG-545。测之前先做第 0 条。
## 0. 确认测的是新版本
浏览器打开 `https://staging.jyotisha.chat/api/health`,看 `deployment.gitCommit` 前 8 位是否等于本单合入 staging 后的提交。不一致 = 先别测。
## 1. 时间卡跟在「这次的结果」那句下面(P0 · BUG-544)
1. 把一场校正问到助手给出这次的结果。
2. 看**最新**那条助手消息下面。
- ✅ 预期:旁白以「我按你说的经历认真分析过了,下面是这次的结果。」收尾;`当前可能的出生时间` 卡紧挨着这句,能点「采用此时间」。
- ❌ 失败:卡出现在更早的采集题或区分题下面,最新旁白下面没有卡。
## 2. 采集题还在问时不要出采用卡(P0 · BUG-544)
若过程中还在问「工作上呢,还记得哪年入职…」这类口述题:
- ✅ 预期:这题下面没有采用卡;答完并出采用旁白后,卡才出现在最新旁白下。
## 3. 旁白像对人说话(P1 · BUG-545)
采用旁白:
- ✅ 预期:不出现「当前候选」或「先用着」。收尾是「我按你说的经历认真分析过了,下面是这次的结果。」单分钟只说一遍钟点(例如「眼下更站得住的是 05:15」),不把同一时刻先当范围再当代表分钟。仍有「不是已确认的唯一出生分钟」。
- ❌ 失败:出现「剩下的题分不开当前候选」、「范围是 05:15,代表分钟 05:15」,或「可以先用着」。
@@ -12,7 +12,7 @@
1. 新开一个生时校正会话,按平常走完区分题。
2. **点选最后一道区分题**(不要用采集题「没有」代替)。
- ✅ 预期:同一轮出现「当前可能的出生时间」采用卡;旁白说出为什么停(分不开两个相邻分钟)、现在的范围和代表分钟,并以「可以从下面选一个先用着」收尾。
- ✅ 预期:同一轮出现「当前可能的出生时间」采用卡;旁白说出为什么停(分不开两个相邻分钟)、现在的范围和代表分钟,并以「我按你说的经历认真分析过了,下面是这次的结果。」收尾。
- ❌ 改造前(BUG-521):点选入口旁白仍是模板句,Agent 没上场。
采集题路径仍要能走: