Files
Jyotisha/docs/superpowers/specs/2026-07-20-conversational-birth-time-rectification-design.md
T

453 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 首屏卡片聊天式生时校正设计
日期:2026-07-20
状态:设计已确认,等待书面审核
## 1. 背景
产品当前存在两条名称相同、业务职责却不同的“生时校正”路径:
1. 初始化流程调用 `/api/birth-time-journey`,以动态选择题推进持久化案例;
2. 首页卡片把“生时校正”或“再次校正”放入输入框,发送后调用普通 `/api/consult`,由咨询工作流和 Agent 生成有星盘依据的自然语言分析。
初始化路径具备案例、轮次、候选、恢复和确认记录,但其宽泛年份区间选择题无法承载真实人生证据,也把高认知成本的专业服务变成了首次使用门槛。首页卡片路径能够生成专业的候选解释、技术边界和高区分度事件追问,却只形成普通聊天消息,不能持久化正式校正进度或安全更新当前排盘时间。
本设计将两条路径合并为一条:
> 首屏卡片和自然聊天是唯一用户校正流程;真实星盘推算负责判断;账户级校正案例负责保存证据、候选、费用、版本和最终确认。
## 2. 与既有设计的关系
本设计对现有文档作如下收敛:
- 取代 `2026-07-18-agent-guided-birth-time-rectification-design.md` 中“动态选择题是默认用户主流程”的决策;
- 保留该设计中的确定性候选计算、服务端证据边界、幂等动作、轮次版本、评分任务和终态安全门;
- 扩展 `2026-07-19-private-consultation-entrypoints-design.md``birth_time_rectification` 不再只是普通咨询提示词入口,而是正式校正案例入口;
- 取代 `2026-07-19-birth-time-terminal-completion-design.md` 中“低置信代表时间可直接采用”的新流程规则;新流程只能在明确候选确认协议成功后替换当前排盘时间;
- 历史案例和审计记录不删除。尚未完成的旧协议案例通过新修订案例承接,不原地改写历史协议和原始证据。
## 3. 目标
- 初始化只采集用户实际知道的出生事实,不强制完成生时校正;
- 未校正用户可以进入首页并自由选择使用未校正时间咨询,或先校正再咨询;
- 首屏卡片成为开始、继续和再次校正的唯一产品入口;
- 保留现有卡片咨询能够生成的专业候选解释、技术依据和动态事件追问;
- 将每轮自然语言对话归一化为正式事件证据,并持久化候选变化和推算依据;
- 支持刷新、换设备、新对话、暂停和网络重试后的安全恢复;
- 再次校正期间继续使用原确认时间,只有用户明确确认新候选后才替换;
- 一次校正案例固定收费,同一案例内的所有追问和恢复不重复收费;
- 校正完成后恢复用户之前保存的普通咨询问题。
## 4. 非目标与硬边界
- 不让大模型直接决定、写入或确认出生分钟;
- 不把普通聊天消息当作唯一校正记录;
- 不用尚未发生的未来窗口作为校正评分证据;
- 不以性格描述、情绪标签或宽泛年份区间作为默认高质量证据;
- 不要求每轮只能点击固定选项;
- 不因用户选择“都不符合”而产生异常或强迫其补充;
- 不在新校正完成前覆盖当前已确认时间;
- 不删除历史案例、旧候选、原始填报和用户确认记录;
- 不在本设计中改变普通咨询的模型选择和常规扣点价格。
## 5. 已确认的业务规则
### 5.1 初始化与软引导
初始化只采集:
- 出生日期;
- 出生地点;
- 用户知道的具体时间或大致时段;
- 时间来源;
- 用户声明的不确定范围或文字线索。
用户无需完成校正即可进入首页。未校正用户发起依赖本命盘的普通咨询时,界面提供两种选择:
1. `先用未校正时间询问`:在当前对话内继续,所有相关回答标明时间未经校正并降低分钟敏感结论的置信度;
2. `先校正再询问`:保存原始问题,启动或恢复校正案例,校正完成后再接续原问题。
“先用未校正时间询问”的选择只在当前聊天会话有效。新建聊天时重新温和提示一次,不逐条消息重复打断。用户只有时段或完全不知道具体分钟时,不得虚构工作时间;可以进入校正,或进行不依赖精确出生时间的一般咨询。
### 5.2 卡片状态
- 没有历史案例:显示 `开始生时校正`
- 存在未完成案例:显示 `继续上次校正`,并提供次级操作 `重新开始`
- 已有确认时间且没有未完成修订:显示 `再次校正`
- 新修订进行中:继续使用旧确认时间,并标记 `新校正进行中`
- 暂停、失败或放弃新修订不影响旧确认时间;
- 删除或新建聊天不删除、不重置校正案例。
### 5.3 计费
- 固定点数由服务端产品配置提供,并在卡片启动操作旁明确显示;客户端不得硬编码或自行提交价格;
- 启动全新校正案例时预留一次固定点数;
- 正式案例创建成功并展示第一轮有效专业分析后完成扣点;
- 案例创建失败、服务不可用或第一轮有效分析未生成时释放预留点数;
- 暂停、刷新、换设备和继续同一案例不重复收费;
- 同一案例中的追问、事件提取、候选重算和最终确认均包含在本次固定费用内;
- 已完成或用户明确放弃后发起全新案例,重新收取一次固定费用;
- 校正前保存的普通咨询问题不提前扣咨询点数。校正完成后,用户确认继续回答时才按普通咨询规则扣点。
- 上线前已经存在的未完成旧协议案例免费承接一次新对话式修订,避免用户为历史缺陷和协议迁移再次付费;承接后的新案例仍使用标准费用回执标记为迁移豁免。
## 6. 目标架构
```mermaid
flowchart LR
UI["首屏卡片与聊天界面"] --> ORCH["校正对话编排器"]
ORCH --> CALC["确定性星盘与候选计算"]
CALC --> PACKET["技术差异与证据请求包"]
PACKET --> AGENT["专业解释与动态追问 Agent"]
AGENT --> VALIDATE["输出契约校验"]
VALIDATE --> UI
ORCH --> CASE["账户级校正案例"]
CASE --> EVIDENCE["事件证据与候选修订"]
EVIDENCE --> CALC
CASE --> CONFIRM["原子候选确认"]
CONFIRM --> PROFILE["账户当前排盘时间"]
```
### 6.1 首屏卡片与聊天界面
该层只负责呈现和用户输入:
- 展示完整专业解释;
- 展示事件方向按钮,例如事业、学业、搬迁;
- 始终保留自由输入;
- 展示结构化事件摘要并允许纠正;
- 展示暂停、继续、放弃和最终确认;
- 不在客户端计算候选、设置置信度或决定状态转换。
聊天会话是呈现载体,不是校正事实来源。聊天删除后,案例仍可从任意新聊天继续。
### 6.2 校正对话编排器
编排器是每轮业务动作的统一入口,负责:
- 创建、恢复或修订账户级案例;
- 读取当前声明时间、旧确认时间、候选范围和既往证据;
- 调用确定性计算生成候选差异;
- 调用 Agent 生成面向用户的专业解释和下一步事件请求;
- 校验 Agent 输出与计算包一致;
- 保存用户原文、事件提取、技术回执、可见解释和候选修订;
-`actionId``turnVersion` 保证幂等和并发安全;
- 管理固定费用、暂停、恢复、放弃和原始咨询问题接续。
### 6.3 确定性计算与 Agent 的边界
确定性计算负责:
- 建立和扫描候选时间范围;
- 计算 D1 稳定性、上升边界距离和分钟敏感结构;
- 比较 D9、D10 等分盘及当前支持的技术层;
- 生成不同候选之间可验证的差异;
- 根据已经发生的事件证据重新评分;
- 产生候选范围、代表时间、可信边界和停止条件。
Agent 负责:
- 把技术包解释成自然、可理解的中文;
- 说明当前时间为何只能作为填报时间或待验证候选;
- 选择当前最有区分度且用户容易回答的事件领域;
- 询问具体、已发生、可给出日期精度的人生事件;
- 根据用户回答调整下一轮问题方向;
- 在信息不足时诚实说明,而不是生成虚假精确分钟。
Agent 不得发明技术包中不存在的盘面事实、候选时间、置信度、评分权重或确认状态。
## 7. 领域模型与持久化
### 7.1 `RectificationCase`
账户级校正案例至少包含:
```ts
type RectificationCase = {
id: string;
userId: string;
protocol: "conversational-evidence-v3";
status: "starting" | "active" | "paused" | "confirming" | "completed" | "abandoned";
turnVersion: number;
revisionOfCaseId: string | null;
importedFromCaseId: string | null;
baselineActiveTime: string | null;
declaredBirthInput: DeclaredBirthInput;
currentCandidate: CandidateRevision | null;
pendingConsultationQuestion: string | null;
billingState: "reserved" | "charged" | "released" | "migration_waived";
billingReservationId: string | null;
billingReceiptId: string | null;
};
```
`baselineActiveTime` 在再次校正期间保持为账户当前时间。候选结果保存在案例内部,不得在确认前写入账户当前排盘时间。
### 7.2 `RectificationTurn`
每轮保存:
- 当前案例版本;
- 用户可见专业解释;
- 结构化技术依据和计算版本;
- 推荐事件方向;
- 请求的日期精度;
- 用户原始回答;
- 事件提取结果;
- 本轮前后候选范围;
- Agent、模型和输出校验回执;
- 幂等动作标识与时间戳。
用户可见解释需要保留,以便恢复后理解为何进入当前问题;技术包使用结构化字段存储,不能依赖重新调用模型复原历史理由。
### 7.3 `LifeEventEvidence`
事件证据包含:
```ts
type LifeEventEvidence = {
id: string;
caseId: string;
rawText: string;
domain: "career" | "education" | "relocation" | "relationship" | "family" | "other";
eventSummary: string;
dateValue: string | null;
datePrecision: "day" | "month" | "year" | "range" | "unknown";
extractionStatus: "clear" | "needs_clarification" | "corrected";
sourceTurnId: string;
};
```
系统先保存用户原文,再保存提取结果。信息清楚时无需增加强制二次确认,但必须在下一轮以可见摘要回显并允许用户纠正;信息模糊时先追问,不进入评分。
## 8. 每轮响应契约
新校正响应必须同时包含用户可见解释与机器控制数据:
```ts
type ConversationalRectificationTurn = {
caseId: string;
turnVersion: number;
narrative: string;
candidate: {
status: "declared" | "pending_validation" | "ready_for_confirmation" | "confirmed";
representativeTime: string | null;
rangeStart: string | null;
rangeEnd: string | null;
};
technicalReceipt: {
calculationVersion: string;
stableLayers: string[];
sensitiveLayers: string[];
candidateDifferenceRefs: string[];
};
evidenceRequest: {
domains: EvidenceDomain[];
datePrecision: "month_preferred" | "year_accepted";
freeTextAllowed: true;
} | null;
actions: RectificationAction[];
};
```
界面先展示 `narrative`,再展示事件方向按钮和自由输入框。按钮只表示用户希望从哪个领域开始,不直接代表支持某个候选的评分证据。
### 8.1 回答节奏
- 首轮:完整解释当前候选、可用边界、稳定层、敏感层和最有区分度的事件方向;
- 中间轮:聚焦新证据导致的候选变化、已记录事件摘要和下一步;
- 最终轮:完整总结候选时间、支持证据、残余不确定性、确认影响和旧时间替换规则。
未来窗口可以作为背景解释,但必须标记为技术候选窗口,且不能计入校正评分。
## 9. 业务流程
### 9.1 从卡片主动开始
```mermaid
flowchart TD
A["用户点击开始或再次校正"] --> B["创建案例并预留固定点数"]
B --> C["计算当前候选与敏感差异"]
C --> D["生成并校验首轮专业解释"]
D -->|"成功"| E["保存首轮并完成扣点"]
D -->|"失败"| F["释放点数并保留原状态"]
E --> G["用户选择事件方向或自由描述"]
G --> H["保存原文并提取事件证据"]
H --> I{"证据是否清楚"}
I -->|"否"| J["自然语言追问"]
I -->|"是"| K["重新评分候选"]
K --> L{"是否达到确认条件"}
L -->|"否"| C
L -->|"是"| M["展示完整候选确认"]
M --> N["用户明确确认"]
N --> O["原子更新当前排盘时间"]
```
### 9.2 从普通问题分流
用户选择“先校正再询问”后:
1. 原始问题保存到案例;
2. 普通咨询不扣点、不生成回答;
3. 启动或恢复校正并按固定校正费用处理;
4. 校正完成后提示 `使用新确认时间继续回答原问题`
5. 用户确认继续时,创建普通咨询扣点并使用新确认时间回答;
6. 校正暂停时,原始问题继续保留。
### 9.3 旧案例承接
`dynamic-choice-v2` 和 legacy 案例不原地改写。用户继续旧未完成案例时:
1. 读取旧案例最新候选范围、原始资料和已经形成的有效证据;
2. 创建 `conversational-evidence-v3` 修订案例,设置 `importedFromCaseId`
3. 保留旧案例为只读历史;
4. 新案例首轮解释当前继承的候选范围,并从真实技术差异生成新的事件追问;
5. 不再向用户恢复宽泛年份区间选择题。
该承接属于同一未完成任务,使用一次 `migration_waived` 费用回执,不收取固定费用;只有明确放弃或完成后开启全新案例才按当前价格收费。
## 10. 异常恢复与一致性
### 10.1 启动与计费失败
- 案例创建、第一轮计算或第一轮有效解释失败时释放预留点数;
- 不显示成功状态,不创建无法继续的收费案例;
- 同一启动 `actionId` 重试时返回同一案例和费用结果。
### 10.2 网络错误
- 502、连接中断和非 JSON 响应使用同一幂等动作进行有限重试;
- 重试失败显示稳定中文错误和可追踪诊断分类;
- 保留用户刚输入的事件,不泄漏 WebKit 原始英文 `DOMException` 文案;
- 部署切换期间未到达业务服务的请求不得产生扣费或轮次推进。
### 10.3 并发与恢复
- 所有推进动作校验案例所有权、`turnVersion``actionId`
- 两台设备同时操作时,旧版本返回“进度已更新”,客户端加载最新一轮;
- 刷新、换设备和新聊天根据账户未完成案例恢复;
- “都不符合”是正常答案:可以直接换事件方向,也可选填说明,不作为错误;
- 删除聊天不级联删除校正案例。
### 10.4 Agent 输出不一致
- `narrative` 中的候选时间、盘面事实和敏感层必须能映射到 `technicalReceipt`
- 输出契约解析失败或事实不一致时,本轮不持久化为已推进状态;
- 可以重试表达生成,但不能重新计算或重复扣费;
- 多次表达失败时展示结构化安全回退,允许稍后继续。
### 10.5 原子候选确认
最终确认在单个数据库事务或等价原子 RPC 中完成:
1. 校验用户所有权;
2. 校验案例仍处于最新 `confirming` 轮次;
3. 校验候选结果、代表时间和技术版本未变化;
4. 写入用户确认和动作回执;
5. 更新账户当前排盘时间及状态;
6. 关闭本次案例;
7. 保留旧时间、原始填报、候选历史和完整证据链;
8. 返回待接续的普通咨询问题。
任一步失败均不得修改账户当前排盘时间。
## 11. 安全与隐私
- 案例、事件、候选和费用记录只能由服务端以经过身份验证的用户上下文访问;
- 用户只能读取自己的案例和用户可见解释,内部候选分区、评分权重和系统提示不下发;
- 不在日志、设计文档、测试夹具或错误消息中保存访问令牌、刷新令牌、Cookie、邮箱、用户 UUID 或真实出生资料;
- 生产问题复现使用脱敏夹具和请求形状,不复用用户粘贴的认证凭据;
- 聊天删除策略与校正案例生命周期独立,二者都必须具有所有者级 RLS 或等价服务端所有权校验。
## 12. 测试与验收
### 12.1 核心业务场景
1. 新用户只填写基础出生资料即可进入首页;
2. 未校正用户可选择使用未校正时间,或先校正再询问;
3. 使用未校正时间的选择仅在当前聊天有效;
4. 卡片能开始、继续和再次校正;
5. 第一轮有效解释生成后只扣一次固定费用;
6. 第一轮失败自动释放点数;
7. 暂停、刷新、换设备、新聊天和旧案例承接不重复收费;
8. 聊天删除不删除校正案例;
9. 再次校正期间旧确认时间持续生效;
10. 最终确认原子替换当前时间;
11. 校正完成后恢复原普通问题,并在用户确认继续时按普通咨询收费。
### 12.2 回答质量契约
首轮专业解释必须包含:
- 当前时间属于填报时间还是待验证候选;
- 当前候选可使用到什么程度;
- 真实星盘中的稳定部分和分钟敏感部分;
- 为什么选择当前事件领域;
- 至少两个适合验证的已发生事件方向;
- 对具体年月和事件描述的请求;
- 未来窗口不属于既成验证证据的边界。
建立一份完全脱敏、使用合成出生资料的专业首轮基准夹具。回归测试验证系统升级后仍能生成候选解释、技术依据和具体事件追问,而不是退化为无依据的宽泛年份按钮。
以下形式不得作为默认有效证据流程:
```text
哪一个时间段更接近一次持续的生活压力变化?
20062011
20112016
不确定
都不符合
```
只有当区间来自当前候选的真实技术差异、已解释区分目的,并且后续仍收集具体已发生事件时,区间按钮才可作为辅助入口。
### 12.3 技术与异常测试
- 重复请求不重复扣费、建案例或推进轮次;
-`turnVersion` 不能覆盖最新进度;
- “都不符合”正常换方向;
- 502、非 JSON 和 WebKit 返回稳定中文错误;
- 部署切换失败不产生费用或半完成轮次;
- Agent 事实与技术回执不一致时拒绝推进;
- 模糊事件不进入评分,用户纠正后使用修订证据;
- 未来事件不进入评分;
- 动态和新协议候选均走各自正确的确认路径;
- 确认任一步失败时保留旧时间;
- 所有者隔离、聊天删除 RLS 和案例读取权限通过认证端到端测试。
### 12.4 浏览器验收
至少覆盖桌面和 390px 移动宽度:
- 初始化可跳过校正并进入首页;
- 未校正软分流;
- 卡片的开始、继续和再次校正文案;
- 首轮完整专业解释、事件方向按钮和自由输入;
- 中间轮候选变化解释;
- 暂停、恢复、网络失败和中文错误;
- 最终候选依据、确认影响和原问题接续;
- 键盘、触屏和屏幕阅读器可完成全流程。
## 13. 分阶段交付边界
1. 先补齐候选确认、聊天删除、非 JSON 错误和部署瞬时失败等现有闭环问题;
2. 建立 `conversational-evidence-v3` 案例、轮次、事件与固定费用契约;
3. 将卡片接入正式案例和专业解释双层响应;
4. 把初始化改为事实采集和软分流,停止创建新的选择式案例;
5. 为旧未完成案例增加只读导入的新修订承接;
6. 完成认证端到端、移动端和生产可观测性验证后,再移除旧选择式用户界面。
旧协议数据、迁移代码和读取兼容在确认没有活跃依赖前保留,不以删除历史实现作为首发条件。
## 14. 成功标准
- 用户不再因生时校正被阻塞在初始化;
- 首屏卡片是唯一可见校正入口;
- 第一轮仍具备当前专业咨询式候选解释和真实事件追问能力;
- 每个专业解释都能追溯到技术回执,每个评分证据都能追溯到用户原文;
- 同一案例跨聊天、刷新和设备恢复且只收费一次;
- 未校正时间可由用户主动选择临时使用,但不会被自动标记为已确认;
- 再次校正不会提前覆盖旧确认时间;
- 最终确认原子完成,并能接续用户原普通问题;
- “都不符合”、候选确认、删除聊天和部署瞬时失败均有稳定、可恢复的生产行为。