docs(tasks): collection-flow redesign brief (BUG-646~648); supersede exhausted-gate brief
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
3cd7a95d58
commit
98bc79fae4
@@ -99,7 +99,8 @@
|
||||
| `TASK-rectification-latent-audit-20260910.md` | `PROGRESS-rectification-latent-audit-20260910.md` | 顺带审计:账本派生同年键误杀 `known_event_quality`(BUG-637,BUG-389 复发);双轨一致性按 31 分钟逐分判冲突并降置信度、与报告两套口径(BUG-638);不可分宽度按簇代表分钟少算(BUG-639);引擎与推断层两套代表分钟、回执宫位表不是卡片那一分钟(BUG-640);另 8 条观察项 | 已验收通过(2026-09-10,Claude;环境缺口:`next build` / 真人走查) | `codex/rectification-unwritten-evidence-claim-20260910` |
|
||||
| `TASK-rectification-collect-semantics-20260910.md` | `PROGRESS-rectification-collect-semantics-20260910.md` | 产品决策三改:Skill 去掉「财务/健康只有主动说才问」并清空 Python `VOLUNTEER_ONLY`,升 10.0.22(BUG-641);带年份线索的采集题优先、题干带线索不矛盾,推翻 BUG-539 的整句去前缀(BUG-642);删掉「没有/记不清」原字匹配,分类器分 no/unsure 两类(BUG-643) | 待验收 | `52db714b`(BUG-641~643) |
|
||||
| `TASK-rectification-superseded-focus-duplicate-20260910.md` | `PROGRESS-rectification-superseded-focus-duplicate-20260910.md` | P0:一轮两次 batch 让感情采集题被顶替成 superseded 行;题号唯一约束含已结束行、汇总只聚合 declined/skipped,计划层看不见→撞号 `duplicate_focus` 被当「已问过」→出口误走交付旁白无卡(BUG-644);交付口吻与 `can_adopt=false` 矛盾(BUG-645) | 待验收(环境缺口:`next build` / 真人走查) | `a3a51c32`(BUG-644/645) |
|
||||
| `TASK-rectification-exhausted-gate-exit-20260910.md` | `PROGRESS-rectification-exhausted-gate-exit-20260910.md` | 五领域全拒答 + 三件带月经历:门槛句后无载体、客户端误报「没有拿到下一个问题」并循环「接着问」(BUG-646);第三件被留作 holdout 导致永远没有选择题(BUG-647)。含产品建议:一次性开放追问 + 终态标记 + 穷尽后释放 holdout | 待执行(决策 3 建议执行前向产品确认) | `codex/rectification-exhausted-gate-exit-20260910` |
|
||||
| `TASK-rectification-exhausted-gate-exit-20260910.md` | `PROGRESS-rectification-exhausted-gate-exit-20260910.md` | 五领域全拒答 + 三件带月经历:门槛句后无载体、客户端误报「没有拿到下一个问题」并循环「接着问」(BUG-646);第三件被留作 holdout 导致永远没有选择题(BUG-647)。含产品建议:一次性开放追问 + 终态标记 + 穷尽后释放 holdout | 已被取代(并入采集重设计单) | — |
|
||||
| `TASK-rectification-collection-redesign-20260910.md` | `PROGRESS-rectification-collection-redesign-20260910.md` | 产品口径:用户先说、系统从已说的事锚定追问、不得用生日推年份、不得说「领域」、永远交付结果。S0 开场→S1 自由采集≤2 轮→S2 锚定补全≤4 问→S3 选择题(≥4 件才留 holdout)→S4 交付卡 + 暂定采用。撤回 BUG-642 年份线索与 BUG-646 单终态;Skill 10.0.23(BUG-646~648) | 待执行 | `codex/rectification-collection-redesign-20260910` |
|
||||
|
||||
### 聊天主链路与首页
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# TASK · 生时校正采集流程重设计:用户先说、系统再从已说的事往下追、永远给结果(2026-09-10)
|
||||
|
||||
- 基线:`origin/staging` @ `3cd7a95d`(代码 `52db714b`,已部署;含 BUG-635~645)
|
||||
- 分支:`codex/rectification-collection-redesign-20260910`,基于 `origin/staging`
|
||||
- **本单取代** `TASK-rectification-exhausted-gate-exit-20260910.md`(BUG-646/647)的决策 1、2、3;那份不再单独领取,其 BUG 编号并入本单。BUG-641/642 里「采集题带年龄段年份线索」的口径被本单推翻。
|
||||
- 执行方:coding agent;验收:Claude
|
||||
- BUG 编号起点:**BUG-648**(646/647 已占用,含在本单)
|
||||
- Skill:本单改方法覆盖顺序与采集口径,**升 10.0.23**(部署后先验旧版本历史可打开,BUG-621)。
|
||||
- 不改引擎计分、不改确认门(唯一分钟仍关)。
|
||||
|
||||
## 0. 产品口径(产品负责人 2026-09-10,原话要点)
|
||||
|
||||
1. Agent 一上来就按领域一个个追问,年份还是拿生日推出来的;应该**先等用户说出有价值的经历**,再从这些经历往下问。
|
||||
2. 追问时**不得说「任何领域」「领域不限」**——用户不知道有哪些领域;要给具体例子。
|
||||
3. 生时校正**必须走到结果**:要么直接成功,要么细节不全就问用户补全、补完拿结果。不允许流程走完告诉用户「做不了」。
|
||||
|
||||
## 1. 现状为什么违反这三条
|
||||
|
||||
| 现状 | 代码位置 | 违反 |
|
||||
| --- | --- | --- |
|
||||
| 开场问完第一件,立刻按 `DATED_COLLECT_ORDER`(家人→学业→财务→迁居→健康→事业→感情)逐领域轮转 | `method-followup.ts` `nextDatedCollectFollowup`(L1405 在覆盖链之前) | 口径 1:没等用户说完就开始盘问 |
|
||||
| 轮转题干带「2020 年前后 / 2023 年前后」——这些年份来自 `_age_band_year`:出生年 + 该领域典型年龄段中点 | `event_probes.py` `DOMAIN_CATALOG.age_lo/age_hi`、BUG-642 的 `COLLECT_QUESTION_YEAR_CUE` | 口径 1:「干凭生日来推」。这是我今天上午写进 BUG-642 的口径,错了,本单撤回 |
|
||||
| 六个领域全「没有」后,出口只写「还差 1 件带月份的经历,领域不限」,不落焦点、无按钮 | `persistExhaustionCollect`、BUG-558/627 决策 | 口径 2、3:说了「领域不限」,且流程到此为止 |
|
||||
| 三件带年月经历里一件被留作 holdout,训练门要 3 件,于是要 4 件才出第一道选择题;没有一句文案说明 | `split-holdout.ts` `MIN_EVENTS_TO_RESERVE_HOLDOUT=2`、`MIN_ACCEPTANCE_EVENTS=3` | 口径 3:用户按要求给了 3 件,得到的是「还差 1 件」 |
|
||||
| 门关时区间不可采用(`selection_allowed = acceptance_allowed`) | `decision_policy.py` L681 | 口径 3:门关 = 没有结果 |
|
||||
|
||||
## 2. 目标流程(状态机)
|
||||
|
||||
```
|
||||
S0 开场 ─▶ S1 自由采集(用户主导,≤2 轮邀请)─▶ S2 锚定补全(从已说的事推导,≤4 问)─▶ S3 区分选择题 ─▶ S4 交付结果
|
||||
▲ │
|
||||
└────────────── 用户任何时候补一件带年月的事 ◀─────────────────┘
|
||||
```
|
||||
|
||||
### S0 开场(文案基本不变)
|
||||
|
||||
一句说明窗口与做法,一句「最后给区间和代表分钟」,一句邀请:「先说你最容易想起的一两件,比如上大学、第一份工作、搬到别的城市、谈恋爱或结婚、家里添丁或长辈住院、生病受伤,年月大概就行。」不写年份。
|
||||
|
||||
### S1 自由采集(用户主导)
|
||||
|
||||
- 用户每说一批,batch 写入、复述「记下了:…」,然后**只问一句「还有吗」**,例子只列**还没提过的种类**,最多 4 个,用具体事物不用领域词:「还有吗?比如第一份工作、搬到别的城市、谈恋爱或分手、家里添丁或长辈住院。」
|
||||
- 最多两轮邀请。用户说「没有了 / 就这些 / 记不清」→ 进 S2。训练门一开(3 件带月 / 2 类)→ 直接进 S3,不再邀请。
|
||||
- 不问带年份线索的领域题;不按领域轮转。
|
||||
|
||||
### S2 锚定补全(从已说的事推导,不看生日)
|
||||
|
||||
每个已记事件按 `kind` 派生 1–2 个**锚定追问**,一次只问一句,答「没有 / 记不清」即跳过,最多 4 问:
|
||||
|
||||
| 已记事件 | 派生追问(题干里必须带上那件事的年份或名字,年份来自用户,不来自生日) |
|
||||
| --- | --- |
|
||||
| `education_start`(上大学 2016) | 「2016 年上大学是搬到别的城市住吗?」 |
|
||||
| `education_completion`(毕业 2020) | 「2020 年毕业后第一份工作大概哪年哪月开始?」 |
|
||||
| `career_change` / 第一份工作 | 「那之后有没有换过工作或升过职?大概哪年?」 |
|
||||
| `relocation` | 「搬过去之后,工作或感情有没有跟着变?哪年?」 |
|
||||
| `relationship_start` | 「后来是分开了还是结婚了?大概哪年?」 |
|
||||
| `relationship_end` / `separation` | 「分开前后有没有换工作或搬家?」 |
|
||||
| `self_health_event`(外伤 2024-10) | 「2024 年 10 月那次之后,工作或住处有没有变?」 |
|
||||
| `family_event` | 「那件事前后你自己有没有搬家或换工作?」 |
|
||||
| 只有学业、没有工作 | 「毕业后第一份工作大概哪年开始?」(这是最常见的缺口,优先级最高) |
|
||||
|
||||
- 派生规则放服务端(`anchoredFollowups(evidence)`),题干模板固定,Agent 只做口语润色,不得改年份、不得加生日推出来的年份。
|
||||
- 4 问之后仍不足 → 进 S4(不是死路)。
|
||||
|
||||
### S3 区分选择题(现有逻辑,改两处)
|
||||
|
||||
- **holdout 只在不影响筛选时保留**:带月事件 ≥4 才留 1 件作 holdout;恰好 3 件时全部参与训练,回执 `holdout.status="not_reserved_min_events"`,报告 Real Case Calibration 行写 `not reserved`。确认门不变(本来就关)。
|
||||
- 选择题、旁白、时间线口径不变(BUG-634/606)。
|
||||
|
||||
### S4 交付结果(永远有)
|
||||
|
||||
- 触发:S3 问完;或 S2 四问用尽;或用户说「先这样」。
|
||||
- 内容:现有区间卡(`range_delivery` 三列)+ 一句定性 + **一句具体的「再补什么能收窄」**:从 S2 未答的锚定追问里取第一条,写成「如果还记得毕业后第一份工作是哪年开始的,范围还能再收一截」。绝不写「任何领域」「领域不限」「做不了」「材料不够」。
|
||||
- 训练门关时也交付:卡片标「暂定」,`selection_allowed` 对「暂定采用」放开(写入 `accepted_time` 且 `acceptance_kind="provisional"`),排盘可用,报告与咨询头部写「暂定出生时间(N 件经历)」;正式「采用」仍走原门。这是对 `selection_allowed = acceptance_allowed` 的有意放宽,**只放采用,不放确认**。
|
||||
- 交付后 Case 不关:用户随时再补一件带年月的事,回到 S3/S4 重算,卡片更新。
|
||||
|
||||
### 文案硬规则
|
||||
|
||||
- 用户可见文案禁止:领域、任何领域、领域不限、方法覆盖、分盘、探针、训练门、holdout、做不了、材料不够。
|
||||
- 每个「还有吗」和「再补什么」都必须带 ≥2 个具体例子,例子只从未覆盖的种类里选。
|
||||
- 静态词表合同(`agent-voice-copy-contract`)加以上禁词。
|
||||
|
||||
## 3. 决策记录
|
||||
|
||||
1. 撤回 BUG-642「采集题带年龄段年份线索」:`COLLECT_QUESTION_YEAR_CUE` 删除;`evidence_collection_probes` 的 age_band 年份只用于内部排序,不进任何题干。
|
||||
2. 撤回 BUG-646 单决策 2(终态 = 门槛句 + 先这样按钮):终态改为 S4 的交付卡。撤回决策 3 的「释放 holdout」:改为「≥4 件才留 holdout」的静态规则,不需要「穷尽后释放」的动态分支。
|
||||
3. BUG-558 的防复发(不得无限循环「再说一件」)保留:S1 邀请 ≤2 轮、S2 追问 ≤4 问,都有硬上限,超过即交付。
|
||||
4. 「暂定采用」是新增能力:只影响采用与排盘标注,不影响确认门、不影响唯一分钟声明。
|
||||
5. Skill 10.0.23:把「先走完方法覆盖(感情 → 事业 → 家人 → 职业 → 占问),再对已覆盖领域做精度追问」改为本单 S1→S2→S3→S4;删除「财务与健康…」相关旧句(10.0.22 已删)。
|
||||
|
||||
## 4. 硬红线
|
||||
|
||||
- 不得用出生年推年份写进题干(`grep -n "年前后" user-copy.ts` 只允许出现在带用户年份的锚定模板里)。
|
||||
- S1/S2 上限必须是代码常量并有测试;不得依赖模型自觉。
|
||||
- 「暂定采用」写入必须带 `acceptance_kind`,报告/咨询头部必须能区分暂定与正式。
|
||||
- 既有测试总数不降;被本单推翻的断言(BUG-642 年份线索、BUG-558「不落焦点」、BUG-646 单若已开工)逐条写原值 / 新值 / 原因。
|
||||
- Bug 历史与测试不得含真实用户资料。
|
||||
|
||||
## 5. 任务分解
|
||||
|
||||
- **T1 S1 邀请**(BUG-648):`method-followup.ts` 覆盖链前置一个 `openInviteFollowup(evidence, inviteCount)`,例子从未覆盖种类里选;`invite_count` 落在 conversation summary;≤2。验收:两轮后不再邀请;例子不含已记种类;无「领域」。
|
||||
- **T2 S2 锚定追问**(BUG-648):`anchoredFollowups(evidence, askedKeys)` + 模板表;`persistServerOwnedFocus` 落 `collect:anchor:<kind>:<year>`;≤4。验收:学业两件 → 首问是「毕业后第一份工作」;答「没有」跳下一条;四问后不再问。
|
||||
- **T3 删年份线索**(撤回 BUG-642):删 `COLLECT_QUESTION_YEAR_CUE` 与相关分支;`USER_COLLECT_QUESTION` 保留为 S2 之外的兜底但不再主动轮转。验收:`rectification-spoken-collect.test.ts` 相关断言改写。
|
||||
- **T4 holdout 规则**(BUG-647):`MIN_EVENTS_TO_RESERVE_HOLDOUT` 语义改为「训练 ≥3 后才留」;回执状态;报告行。验收:3 件全训练、4 件留 1。
|
||||
- **T5 S4 交付与暂定采用**(BUG-646):`persistExhaustionCollect` / `ensureNonTerminalTurnExit` 终态改为交付卡 + 「再补什么」句;Python `selection_allowed` 拆成 `provisional_selection_allowed`(候选存在即真)与原 `selection_allowed`;accept RPC 带 `acceptance_kind`;报告头部标注。验收:2 件学业 + 全拒答 → 出交付卡、可暂定采用、无禁词;客户端不出现「没有拿到下一个问题」。
|
||||
- **T6 Skill 10.0.23 + 词表合同 + 记录**:SKILL.md、registry、`case-status.ts`、CHANGELOG、BUG-646~648 历史、`docs/testing/` 真人清单(全拒答路径、只有学业路径、正常路径三条)。
|
||||
|
||||
## 6. 让步顺序
|
||||
|
||||
T5 的「暂定采用」半边可延后(先交付卡、采用仍按原门;写 `BLOCKED.md`);T1~T4 与 T5 的交付卡不可省。
|
||||
|
||||
## 7. 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/rectification-collection-redesign-20260910 .worktrees/rectification-collection-redesign-20260910 origin/staging
|
||||
grep -o "^## BUG-[0-9]*" docs/BUG_HISTORY.md | tail -1
|
||||
cd frontend && npm test -- tests/rectification-spoken-collect.test.ts tests/rectification-exhaustion-exit-20260906.test.ts tests/rectification-surface-state.test.ts tests/skill-registry.test.ts
|
||||
```
|
||||
|
||||
## 8. 验收口径
|
||||
|
||||
- 前端 `tsc --noEmit` 0 错、`npm run lint` 0 error、相关套件 fail=0、测试总数 ≥ 基线;`next build` 后 `/` 仍 Static、首屏 gzip ±2%。
|
||||
- Python 定向 + `run_quality_gate.py --profile quick`。
|
||||
- 部署后先打开一个绑定 10.0.22 的历史校正,再做三条真人清单。
|
||||
@@ -1,3 +1,5 @@
|
||||
> **已被取代**:2026-09-10 产品口径变更,本单决策 1/2/3 由 `TASK-rectification-collection-redesign-20260910.md` 取代,请勿单独领取。
|
||||
|
||||
# TASK · 六条线全答「没有」、只有三件带年月经历时:门槛句之后没有任何载体,页面只剩「没有拿到下一个问题」;第三件被留作验证导致永远没有选择题(2026-09-10)
|
||||
|
||||
- 基线:`origin/staging` @ `fff6da68`(代码 `52db714b`,已部署;含 BUG-635~645)
|
||||
|
||||
Reference in New Issue
Block a user