360 lines
18 KiB
Markdown
360 lines
18 KiB
Markdown
# 专题-01:正文建议接受(Accept Suggestion)实现规范
|
||
|
||
- 版本:v5
|
||
- 更新日期:2026-05-23
|
||
- 目标读者:产品 / 架构 / 前端 / 后端 / 测试
|
||
- 阅读时间:20–35 分钟
|
||
- 边界说明:本文档只收束“接受建议”这条跨文档主链路:用户怎么把 AI 候选写入正文、关联知识草稿怎么保留或失效、正文来源归因怎么落点、事务边界怎么切、前端怎么反馈。精确 Schema、状态机和统一错误模型由后续后端阶段承接;当前阶段以 `架构-02` 和 `架构-04` 为准。
|
||
|
||
## 1. 目标与范围
|
||
|
||
Accept Suggestion 是 AI 候选从待审层(Shadow)进入正文规范数据(Canonical)的唯一合法入口。
|
||
|
||
这个能力要同时解决四件事:
|
||
|
||
- 把候选文本安全写入目标 Block。
|
||
- 写入候选归档和必要的正文来源归因(Block Source Attribution)。
|
||
- 保持“接受正文”和“确认知识”两条用户决策分离,接受候选不写 Local KB。
|
||
- 在修改后合并时,让基于旧候选文本的知识草稿失效,并基于最终正文启动重新提取链路。
|
||
- 把正文、知识、历史与投影边界切干净,避免“看起来成功,其实系统已经脏了”。
|
||
|
||
### 1.1 In Scope
|
||
|
||
- 接受建议(原样接受、修改后合并)
|
||
- 拒绝建议
|
||
- 关联知识草稿的保留 / 失效语义
|
||
- 正文来源归因与授权快照落点
|
||
- 前端正文乐观更新、回滚与冲突处理
|
||
- 审计、归档、outbox 写入与最终一致刷新
|
||
|
||
### 1.2 Out of Scope
|
||
|
||
- 建议生成本身
|
||
- 知识提取算法本身
|
||
- 全书解析的章节批量确认
|
||
- 一致性检查面板本身
|
||
- AST 级精细 diff
|
||
|
||
## 2. 统一语义(先把话说死)
|
||
|
||
### 2.1 三条用户结果路径
|
||
|
||
| 路径 | 正文结果 | 知识草稿结果 | 历史结果 |
|
||
|---|---|---|---|
|
||
| 原样接受 | Suggestion 内容进入目标 Block | 与当前 Suggestion 绑定的草稿保持待确认;不得自动入 Local KB | Suggestion 归档为 accepted |
|
||
| 修改后合并 | `contentOverride` 进入目标 Block | 旧草稿立即失效;AFTER_COMMIT 重新提取新的草稿 | Suggestion 归档为 accepted,并保留 `final_content` 快照(如需要) |
|
||
| 拒绝 | 正文不变 | 关联草稿一起丢弃 | Suggestion 归档为 rejected |
|
||
|
||
### 2.2 为什么“修改后合并”不是新状态
|
||
|
||
- 用户决策仍然是“接受这条建议,只是我改了最终入正文的文本”。
|
||
- 它不应该发明新的 Active 状态,也不应该生成第二套历史状态机。
|
||
- 归档层统一记为 `accepted`,但必须保留“这是 modified merge”的审计语义。
|
||
|
||
### 2.3 Stale Draft 规则
|
||
|
||
只要源文本发生变化,旧知识草稿就必须被视为 stale:
|
||
|
||
- 不能继续确认旧草稿。
|
||
- 不能把旧草稿偷偷并入正式知识。
|
||
- 必须重新走提取 -> 校验 -> 风险分级链路,生成新的草稿。
|
||
|
||
即使源文本没有变化,接受候选也不等于确认知识草稿。知识草稿进入 Local KB 的唯一入口仍是用户在知识确认入口显式确认。正文保存可以触发后续提取、校验和知识治理流程,但不能直接写 Local KB。
|
||
|
||
## 3. 相关 SSOT
|
||
|
||
- 双轨模型:`架构-02-核心数据结构与双轨模型.md`
|
||
- 状态机与端点前后置条件:`架构-04-状态机与约束清单.md`
|
||
- 普通用户系统链路:`流程-02B-普通用户系统处理流程(系统视角).md`
|
||
- 普通用户操作链路:`流程-01B-普通用户操作流程(操作视角).md`
|
||
|
||
本文档只做一件事:把这些分散约束收束成一条可落地的 Accept 链路。
|
||
|
||
## 4. 核心不变式
|
||
|
||
### 4.1 正文与建议
|
||
|
||
- Block 正文是正式正文的唯一真相。
|
||
- Block revision 是写入锚点。
|
||
- AI Suggestion 只保存待审对象;进入终态后必须进入候选归档。
|
||
- 如果候选使用了 AI、市场资产、外部知识或授权知识来源,写入正文 revision 时必须同步写正文来源归因(Block Source Attribution),保留来源链路、授权快照、许可限制和召回状态。
|
||
|
||
### 4.2 关联知识草稿
|
||
|
||
- 生成场景下的知识草稿可以关联到 AI Suggestion,但它仍是独立待审对象。
|
||
- 原样接受时,关联知识草稿保持待确认,不得自动写入 Local KB。
|
||
- 修改后合并时,基于旧候选文本的知识草稿统一失效,不允许继续沿用。
|
||
- 知识草稿确认必须另走知识确认入口,且必须重新校验来源状态、授权快照、source hash、目标版本和风险标记。
|
||
|
||
### 4.3 事务边界
|
||
|
||
- Accept 主事务内不得发起外部 AI / 提取 / 校验调用。
|
||
- 原样接受时,正文写入、候选归档、正文来源归因、关联草稿状态保留、change log、outbox 写入必须放在同一事务里完成。
|
||
- 修改后合并时,正文写入、Suggestion 归档、旧草稿失效与审计仍在主事务;重新提取只能走 AFTER_COMMIT 异步链路。
|
||
|
||
### 4.4 历史与投影
|
||
|
||
- Accept / Reject 后,Active 区不能再看到这条 Suggestion。
|
||
- 接受候选写入正文后,可以触发投影或重新提取 outbox;但投影和提取失败不得反向回滚正文。
|
||
- 投影失败不能反向打断已经成功的 Accept 主事务。
|
||
|
||
## 5. 决策命令语义合同
|
||
|
||
本节只定义产品层面的命令合同,不定义后端 endpoint、请求 JSON 或数据库字段。后续后端阶段可以按此语义设计 API,但不得改变这里的用户决策、幂等、来源和知识草稿边界。
|
||
|
||
### 5.1 Accept 命令
|
||
|
||
Accept 命令必须携带以下语义:
|
||
|
||
| 语义 | 要求 |
|
||
|---|---|
|
||
| commandId / idempotencyKey | 同一 actor、suggestion、command 和目标 revision 的重复提交必须返回同一结果,不得重复写正文、归档或 outbox |
|
||
| actor / work / targetBlock | 当前用户、作品和目标 Block |
|
||
| suggestion | 仍处于 Active / Shadow 的候选 |
|
||
| expectedRevision | 用户决策基于的目标 Block revision,必填 |
|
||
| acceptMode | `accept_as_is` 或 `merge_after_edit` |
|
||
| finalContent | 仅 `merge_after_edit` 需要,表示用户确认写入正文的最终内容 |
|
||
| decisionContext | UI 决策来源、候选版本、质量结果版本和必要审计摘要 |
|
||
| candidateDecisionEnvelope | 候选决策快照或重算请求,必须覆盖输出合规、静态检查、质量结果版本、来源状态、来源事件影响、Action Policy、授权快照、作品资产 feature gate、`expectedRevision` 和幂等结果 |
|
||
|
||
命令结果至少返回以下语义:
|
||
|
||
| 语义 | 原样接受 | 修改后合并 |
|
||
|---|---|---|
|
||
| blockOutcome | 目标 Block 写入成功,revision 递增 | 目标 Block 写入用户最终内容,revision 递增 |
|
||
| suggestionOutcome | Suggestion 离开 Active,进入 Archive,disposition=accepted | Suggestion 离开 Active,进入 Archive,disposition=accepted,并记录 modified merge 摘要 |
|
||
| knowledgeDraftOutcome | 关联草稿保持待确认,仍需单独进入知识确认入口 | 基于旧候选文本的草稿失效,不允许继续确认 |
|
||
| followupTask | 可触发投影刷新,不要求即时返回草稿数量 | AFTER_COMMIT 启动重新提取或投影刷新任务 |
|
||
|
||
### 5.2 Reject 命令
|
||
|
||
Reject 只做三件事:
|
||
|
||
- 迁出 Suggestion
|
||
- 丢弃关联草稿
|
||
- 写历史 / 审计
|
||
|
||
Reject 不得修改正文,不得触发新的提取。
|
||
|
||
### 5.3 幂等与重复提交
|
||
|
||
同一命令重复到达时:
|
||
|
||
- 已成功接受的命令必须返回同一 Block revision、Archive 结果和 followupTask 摘要。
|
||
- 已失败且可重试的命令必须说明失败原因和当前可恢复动作。
|
||
- 已失败且不可重试的命令不得创建新的正文 revision。
|
||
- 同一幂等键携带不同 actor、work、targetBlock、suggestion、`expectedRevision`、授权快照或候选决策输入时,必须返回幂等冲突,不得复用旧结果。
|
||
- Archive、change log、audit log 和 outbox 必须能通过命令幂等语义去重。
|
||
|
||
## 6. 接受前置条件
|
||
|
||
Accept 在任何写正文动作前必须完成前置校验。前置校验失败时,候选不能被接受,正文不能写入。
|
||
|
||
服务端必须消费 Candidate Decision Envelope;如果 Envelope 缺失、过期、质量结果版本不匹配、`expectedRevision` 不匹配、授权快照变化、来源状态变化、作品资产 feature gate 变化或幂等结果不可复用,必须在写正文前重算。重算结果不是提示文案,而是写 Canonical 的硬闸门。
|
||
|
||
| 校验 | 失败结果 |
|
||
|---|---|
|
||
| actor 对作品、Block、Suggestion 有操作权限 | `PERMISSION_DENIED`,不写正文 |
|
||
| Suggestion 仍处于 Active / Shadow,未过期、未失效 | `SUGGESTION_NOT_ACCEPTABLE`,不写正文 |
|
||
| expectedRevision 匹配目标 Block 当前 revision | `REVISION_CONFLICT`,进入显式冲突处理 |
|
||
| Candidate Decision Envelope 允许接受,且包含输出合规、静态检查、质量结果版本、来源状态、授权快照、作品资产 feature gate、expectedRevision 和幂等结果 | 按决策结果阻断、需重验或要求显式确认 |
|
||
| 输出合规、语义安全围栏和静态检查通过 | `OUTPUT_COMPLIANCE_BLOCKED` 或 `STATIC_CHECK_FAILED`,不写正文 |
|
||
| 候选正文 lineage 中所有来源有有效 Authorization Snapshot | `SOURCE_AUTH_INVALID`,候选 invalidated / blocked |
|
||
| 候选正文 lineage 不含 revoked / recalled / delisted / blocked / owner_missing / unauthorized 来源 | `SOURCE_BLOCKED`,候选 invalidated / blocked |
|
||
| 候选使用市场作品资产时,存在有效 `workAssetUsePrecheckId`、owner 预检、授权快照、lineage 和 feature gate | `SOURCE_FEATURE_DISABLED` 或 `OWNER_PRECHECK_REQUIRED`,候选不可接受 |
|
||
|
||
只有与正文无关的关联知识草稿出现 stale、需重验或不可确认时,才允许“正文接受成功、草稿需单独处理”。一旦问题来源参与了候选正文 lineage,就必须阻断正文写入,不能只把 Knowledge Draft 标记为不可确认。
|
||
|
||
## 7. 后端实现规范
|
||
|
||
### 7.1 原样接受事务
|
||
|
||
单个事务内完成:
|
||
|
||
1. 加载 Active Suggestion 并校验归属、状态与过期时间。
|
||
2. 加载目标 Block,并用 `expectedRevision` 做并发保护。
|
||
3. 消费或重算 Candidate Decision Envelope,校验候选来源、授权快照、市场作品资产 feature gate、质量门控、输出合规、静态检查、质量结果版本、幂等结果和当前 Block revision。
|
||
4. 更新 Block 内容与 revision。
|
||
5. 如果候选包含 AI、市场、外部知识或授权知识来源,写 Block Source Attribution。
|
||
6. 将 Suggestion 迁入候选归档(disposition=accepted)。
|
||
7. 保持关联知识草稿为待确认;仅当问题来源没有参与正文 lineage 时,才允许把草稿标记为不可确认或需重验。
|
||
8. 写 change log / audit log。
|
||
9. 写投影或后续提取 outbox。
|
||
|
||
任何一步失败,整笔事务回滚。
|
||
|
||
### 7.2 修改后合并事务
|
||
|
||
单个事务内完成:
|
||
|
||
1. 加载 Active Suggestion 并校验归属、状态与过期时间。
|
||
2. 加载目标 Block,并用 `expectedRevision` 做并发保护。
|
||
3. 消费或重算 Candidate Decision Envelope,校验候选来源、授权快照、市场作品资产 feature gate、质量门控、输出合规、静态检查、质量结果版本、幂等结果和最终正文内容。
|
||
4. 用 `contentOverride` 更新 Block 内容与 revision。
|
||
5. 默认继承上游候选的 lineage、授权快照、许可限制、召回状态和风险标记,并写 Block Source Attribution。
|
||
6. 将 Suggestion 迁入候选归档(disposition=accepted),必要时记录 `final_content`。
|
||
7. 将旧知识草稿标记为失效,不允许继续确认。
|
||
8. 写 change log / audit log,标记这是 modified merge。
|
||
9. AFTER_COMMIT 发布重新提取事件或创建异步任务记录。
|
||
|
||
这里的关键不是任务名字,而是语义:**重新提取只能发生在提交之后,不能把外部调用塞进正文主事务。**
|
||
|
||
如果用户改写后的最终正文确实不再依赖某些授权来源,系统也不能只靠文本差异自动洗白。只有在单独的来源归因证明、原创性确认或人工决策记录成立时,才允许降低对应限制;该过程必须审计,并且不得让 revoked / recalled / delisted / blocked / owner_missing / unauthorized 来源通过改写绕过。
|
||
|
||
### 7.3 Reject 事务
|
||
|
||
单个事务内完成:
|
||
|
||
1. 加载 Active Suggestion。
|
||
2. 校验归属与状态。
|
||
3. 迁入 `suggestion_archive(disposition=rejected)`。
|
||
4. 丢弃关联知识草稿。
|
||
5. 写 `audit_log`。
|
||
|
||
Reject 不得更新 Block,不得创建重新提取链路。
|
||
|
||
### 7.4 失败矩阵
|
||
|
||
| 失败类型 | 正文结果 | 用户可见恢复动作 |
|
||
|---|---|---|
|
||
| 无权限或作品不可访问 | 不写入 | 返回作品或权限提示 |
|
||
| Suggestion 已过期、已归档或已失效 | 不写入 | 重新生成或关闭候选 |
|
||
| 来源 revoked / recalled / delisted / blocked / owner_missing / unauthorized | 不写入,候选 invalidated / blocked | 查看来源摘要、重新生成 |
|
||
| 市场作品资产 feature gate 关闭 | 不写入 | 仅允许阅读、收藏或授权记录,不允许作为 AI 上下文 |
|
||
| owner 预检或 workAssetUsePrecheck 缺失 | 不写入 | 回到作品资产使用预检 |
|
||
| 质量门控 blocked 或 needs_recheck | 不写入 | 重验、重生成或修改后重新评估 |
|
||
| 输出合规或静态检查失败 | 不写入 | 修改输入或重新生成 |
|
||
| revision 冲突 | 不写入 | 基于最新 revision 重试或放弃 |
|
||
| 重复命令 | 不重复写入 | 返回既有结果 |
|
||
|
||
## 8. 前端实现规范
|
||
|
||
### 8.1 状态拥有
|
||
|
||
- 正文 Block:服务端 Block revision 是唯一真相;前端可以乐观展示,但必须能按服务端结果确认或回滚。
|
||
- Active Suggestion:待审区状态持有。
|
||
- 关联知识草稿提示与角标:以最终一致方式刷新,不把瞬时数字当真相。
|
||
|
||
### 8.2 Accept 成功反馈
|
||
|
||
- 原样接受:`已合并,关联知识草稿仍待确认`
|
||
- 修改后合并:`已合并,旧知识草稿已失效,正在重新提取`
|
||
|
||
禁止反馈:
|
||
|
||
- “已合并,发现 N 条草稿待审核”
|
||
- “已合并,草稿已经进入正式知识”
|
||
- “已合并,请稍后看系统是否成功”
|
||
|
||
### 8.3 冲突处理
|
||
|
||
当服务端返回 `409 REVISION_CONFLICT`:
|
||
|
||
- 停止当前乐观链路。
|
||
- 如果本地没有后续编辑,回滚到上一个稳定状态。
|
||
- 如果本地已经继续编辑,进入显式冲突处理态,禁止静默覆盖。
|
||
- 给用户清晰的下一步:放弃本次合并,或基于新 revision 重试。
|
||
|
||
### 8.4 成功后的刷新策略
|
||
|
||
- 成功后移除当前 Suggestion 卡片。
|
||
- 失效相关正文、知识、历史和角标查询。
|
||
- 原样接受优先刷新正文和待确认知识草稿提示;修改后合并优先进入“等待新草稿”状态。
|
||
|
||
## 9. 用户可观察流程
|
||
|
||
### 9.1 原样接受
|
||
|
||
1. 用户点击“接受”。
|
||
2. 正文进入乐观更新状态。
|
||
3. 服务端完成主事务。
|
||
4. 正文切换为已保存态。
|
||
5. Suggestion 卡片从待审区移除。
|
||
6. UI 显示“已合并,关联知识草稿仍待确认”。
|
||
7. 知识视图与历史视图最终一致刷新,用户可进入知识确认入口单独处理草稿。
|
||
|
||
### 9.2 修改后合并
|
||
|
||
1. 用户点击“修改”。
|
||
2. 调整最终入正文的结构化内容。
|
||
3. 点击“修改后合并”。
|
||
4. 服务端完成正文主事务,并让旧草稿失效。
|
||
5. UI 显示“已合并,旧知识草稿已失效,正在重新提取”。
|
||
6. 前端进入等待新草稿状态。
|
||
|
||
### 9.3 Reject
|
||
|
||
1. 用户点击“拒绝”。
|
||
2. Suggestion 离开待审区。
|
||
3. 正文无变化。
|
||
4. 关联草稿一起丢弃。
|
||
|
||
## 10. Acceptance Criteria
|
||
|
||
### Must-Have(P0)
|
||
|
||
1. Accept 成功后,目标 Block 正确更新,revision 正确递增。
|
||
2. Suggestion 成功迁入 Archive,不再留在 Active。
|
||
3. 原样接受时,关联知识草稿不得写入 Local KB,只能保持待确认、需重验或不可确认状态。
|
||
4. 修改后合并时,旧草稿立即失效,不允许继续确认。
|
||
5. 修改后合并只启动重新提取异步链路,不在主事务里做外部调用。
|
||
6. Reject 对正文零副作用。
|
||
7. 409 冲突必须有显式恢复路径。
|
||
8. 成功提示必须区分原样接受与修改后合并两条路径。
|
||
9. 包含 AI、市场、外部知识或授权知识来源的正文 revision 必须写 Block Source Attribution。
|
||
10. 候选正文 lineage 中存在 revoked、recalled、delisted、blocked、owner_missing、unauthorized 或无效授权快照时,Accept 必须失败。
|
||
11. 候选使用市场作品资产时,必须经过作品资产使用预检和 feature gate;否则不能接受。
|
||
12. 修改后合并默认继承上游 lineage 和许可限制,不能用 `contentOverride` 洗白来源。
|
||
13. Accept / Merge 写 Canonical 前必须消费或重算 Candidate Decision Envelope,且 Envelope 必须包含输出合规、静态检查、质量结果版本、来源状态、授权快照、作品资产 feature gate、expectedRevision 和幂等结果。
|
||
|
||
### Should-Have(P1)
|
||
|
||
1. 成功后正文有短暂高亮反馈。
|
||
2. 修改后合并能显示“等待新草稿”的明确状态。
|
||
3. 同一 Block 下重复触发 Accept 时有临时互斥保护。
|
||
|
||
### Nice-to-Have(P2)
|
||
|
||
1. 更细粒度的对比视图。
|
||
2. 建议卡片快捷键。
|
||
|
||
## 11. Test Plan
|
||
|
||
### 11.1 Manual
|
||
|
||
- 原样接受:正文更新,Suggestion 消失,知识视图可看到待确认草稿。
|
||
- 修改后合并:正文更新,旧草稿失效,系统稍后出现新草稿。
|
||
- Reject:正文不变,Suggestion 消失,知识不被污染。
|
||
- 409 冲突:前端进入可恢复状态,不覆盖用户新输入。
|
||
- 重复点击已接受对象:幂等,不重复污染正文与历史。
|
||
|
||
### 11.2 Automated
|
||
|
||
**Backend Unit / Integration**
|
||
|
||
- 原样接受正常路径
|
||
- 原样接受不确认知识草稿
|
||
- 候选正文来源 stale / revoked / recalled / delisted / blocked / owner_missing / unauthorized 时按决策规则阻断接受或要求重验;只有非正文关联草稿允许单独标记需重验
|
||
- Block Source Attribution 写入路径
|
||
- 市场作品资产缺 feature gate / owner 预检 / `workAssetUsePrecheckId` 时阻断接受
|
||
- 修改后合并触发旧草稿失效
|
||
- 修改后合并不能清空上游 lineage、授权快照和许可限制
|
||
- Reject 零正文副作用
|
||
- 409 冲突返回必要信息
|
||
- 投影失败不阻塞主事务
|
||
|
||
**Frontend E2E**
|
||
|
||
- 原样接受成功链路
|
||
- 修改后合并成功链路
|
||
- Reject 成功链路
|
||
- 409 冲突链路
|
||
- 本地脏状态下的失败恢复
|
||
|
||
## 12. 关联阅读
|
||
|
||
- `架构-02-核心数据结构与双轨模型.md`
|
||
- `架构-04-状态机与约束清单.md`
|
||
- `流程-02B-普通用户系统处理流程(系统视角).md`
|
||
- `流程-01B-普通用户操作流程(操作视角).md`
|