[M-AI-05-01] 审计并冻结 Feynman 与复习产物迁移契约 #304

Closed
opened 2026-06-21 15:53:14 +08:00 by wangdl · 1 comment
Owner

类型 / 标签

  • audit
  • architecture
  • feynman
  • migration

风险等级

P0(契约错误将导致全量返工)

依赖

  • M-AI-04 工程实现完成(CONDITIONAL PASS 状态下可并行审计,不可并行开发后续 Issue)

目标

在修改生产链路前,完整确认现有 Feynman 请求、AI 调用、结果写入、FocusItem 和 ReviewCard 创建逻辑。

必须审计

HTTP 入口

真实入口:POST /api/ai-analysis/feynman

确认:Controller、请求 DTO、响应 DTO、状态码、JWT、用户权限、错误响应、iOS/Web/Admin 调用方、重复请求行为。

当前执行链路

追踪:Controller → Service → AiAnalysisService → AiAnalysisJob → Queue Producer → Legacy Worker → Feynman Workflow → Provider → Result Repository → FocusItem / ReviewCard

所有结论必须附:文件路径、类名、方法名、行号。

当前 Job Type

确认数据库和队列真实使用的字符串(不得根据文档猜测)。

输出映射表:使用位置 | 当前值 | 新 Registry 值 | 兼容方式

输入数据

列出模型实际使用的全部输入,分类为:进入 Snapshot / 执行时查询 / 禁止进入 Snapshot

输出 Schema

确认现有业务真实消费的字段(score、correctness、feedback、missingPoints、misconceptions、improvementSuggestions、followUpQuestions、sourceReferences 等),不得因为字段看起来合理就加入新 Schema。

副作用矩阵

逐项确认:Evaluation Result、FocusItem、ReviewCard、UsageLog、学习统计、通知或事件的创建条件、数量、唯一性、失败策略。

FocusItem

确认:创建触发条件、字段来源、knowledgeItemId、knowledgeBaseId、priority/severity、sourceType/sourceId、去重方式、状态默认值。

ReviewCard

确认:创建触发条件、正面内容、背面内容、knowledgeItemId、复习计划、sourceId/sourceType、去重方式、是否已有 Job 或 Result 关联。

幂等

确认稳定业务标识(submissionId / requestId / explanationId),冻结 idempotencyKey 格式(如 feynman:<submissionId>)。

状态与回滚

冻结:Legacy Job 状态、新 lifecycleStatus、公开状态映射、Feature Flag、失败后是否允许重试、如何避免 Legacy 与 Unified 双执行。

输出

新增 docs/architecture/m-ai-05-feynman-migration-contract.md,包含:当前时序图、目标时序图、Snapshot Schema、Output Schema、副作用矩阵、Artifact 矩阵、幂等契约、状态映射、Feature Flag、回滚流程、不确定项。

非目标

  • 不修改代码
  • 不注册 Definition
  • 不创建 Migration
  • 不切换流量

影响范围

src/modules/feynman/src/modules/ai-analysis/src/workers/ai-analysis.worker.tssrc/modules/review/src/modules/focus-item/

验收标准

  • 输出 docs/architecture/m-ai-05-feynman-migration-contract.md
  • 包含当前时序图(真实调用链,附文件路径+行号)
  • 包含目标时序图
  • 冻结 Snapshot Schema(字段清单 + 分类:进入 Snapshot / 执行时查询 / 禁止进入)
  • 冻结 Output Schema(只包含真实被消费的字段)
  • 冻结副作用矩阵(Evaluation Result、FocusItem、ReviewCard、UsageLog、学习统计、通知)
  • 确认 FocusItem 创建条件、数量、去重规则、字段来源
  • 确认 ReviewCard 创建条件、题面/答案来源、去重规则
  • 确认真实 Job Type 字符串(数据库中的实际值)
  • 冻结 idempotencyKey 格式
  • 冻结状态映射表(内部 lifecycleStatus → 旧接口状态)
  • 明确 Feature Flag 机制(建议 FEYNMAN_ENGINE_MODE: legacy | unified
  • 标记所有不确定项

建议执行顺序

第 1 个执行(阻塞所有后续 Issue)

## 类型 / 标签 - audit - architecture - feynman - migration ## 风险等级 P0(契约错误将导致全量返工) ## 依赖 - M-AI-04 工程实现完成(CONDITIONAL PASS 状态下可并行审计,不可并行开发后续 Issue) ## 目标 在修改生产链路前,完整确认现有 Feynman 请求、AI 调用、结果写入、FocusItem 和 ReviewCard 创建逻辑。 ## 必须审计 ### HTTP 入口 真实入口:`POST /api/ai-analysis/feynman` 确认:Controller、请求 DTO、响应 DTO、状态码、JWT、用户权限、错误响应、iOS/Web/Admin 调用方、重复请求行为。 ### 当前执行链路 追踪:Controller → Service → AiAnalysisService → AiAnalysisJob → Queue Producer → Legacy Worker → Feynman Workflow → Provider → Result Repository → FocusItem / ReviewCard 所有结论必须附:文件路径、类名、方法名、行号。 ### 当前 Job Type 确认数据库和队列真实使用的字符串(不得根据文档猜测)。 输出映射表:使用位置 | 当前值 | 新 Registry 值 | 兼容方式 ### 输入数据 列出模型实际使用的全部输入,分类为:进入 Snapshot / 执行时查询 / 禁止进入 Snapshot ### 输出 Schema 确认现有业务真实消费的字段(score、correctness、feedback、missingPoints、misconceptions、improvementSuggestions、followUpQuestions、sourceReferences 等),不得因为字段看起来合理就加入新 Schema。 ### 副作用矩阵 逐项确认:Evaluation Result、FocusItem、ReviewCard、UsageLog、学习统计、通知或事件的创建条件、数量、唯一性、失败策略。 ### FocusItem 确认:创建触发条件、字段来源、knowledgeItemId、knowledgeBaseId、priority/severity、sourceType/sourceId、去重方式、状态默认值。 ### ReviewCard 确认:创建触发条件、正面内容、背面内容、knowledgeItemId、复习计划、sourceId/sourceType、去重方式、是否已有 Job 或 Result 关联。 ### 幂等 确认稳定业务标识(submissionId / requestId / explanationId),冻结 idempotencyKey 格式(如 `feynman:<submissionId>`)。 ### 状态与回滚 冻结:Legacy Job 状态、新 lifecycleStatus、公开状态映射、Feature Flag、失败后是否允许重试、如何避免 Legacy 与 Unified 双执行。 ## 输出 新增 `docs/architecture/m-ai-05-feynman-migration-contract.md`,包含:当前时序图、目标时序图、Snapshot Schema、Output Schema、副作用矩阵、Artifact 矩阵、幂等契约、状态映射、Feature Flag、回滚流程、不确定项。 ## 非目标 - 不修改代码 - 不注册 Definition - 不创建 Migration - 不切换流量 ## 影响范围 `src/modules/feynman/`、`src/modules/ai-analysis/`、`src/workers/ai-analysis.worker.ts`、`src/modules/review/`、`src/modules/focus-item/` ## 验收标准 - [ ] 输出 `docs/architecture/m-ai-05-feynman-migration-contract.md` - [ ] 包含当前时序图(真实调用链,附文件路径+行号) - [ ] 包含目标时序图 - [ ] 冻结 Snapshot Schema(字段清单 + 分类:进入 Snapshot / 执行时查询 / 禁止进入) - [ ] 冻结 Output Schema(只包含真实被消费的字段) - [ ] 冻结副作用矩阵(Evaluation Result、FocusItem、ReviewCard、UsageLog、学习统计、通知) - [ ] 确认 FocusItem 创建条件、数量、去重规则、字段来源 - [ ] 确认 ReviewCard 创建条件、题面/答案来源、去重规则 - [ ] 确认真实 Job Type 字符串(数据库中的实际值) - [ ] 冻结 idempotencyKey 格式 - [ ] 冻结状态映射表(内部 lifecycleStatus → 旧接口状态) - [ ] 明确 Feature Flag 机制(建议 `FEYNMAN_ENGINE_MODE`: `legacy` | `unified`) - [ ] 标记所有不确定项 ## 建议执行顺序 第 1 个执行(阻塞所有后续 Issue)
wangdl added this to the M-AI-05 Feynman 与 ReviewCard 可靠链路 milestone 2026-06-21 15:53:14 +08:00
wangdl added the
priority:p0
area:ai
architecture
audit
labels 2026-06-21 15:53:14 +08:00
Author
Owner

开发完成评论

完成内容

  • 审计了 POST /api/ai-analysis/feynman 的完整 Legacy 调用链(Controller → Service → Queue → Worker → Workflow → Gateway → Provider → Result → FocusItem → ReviewCard)
  • 冻结了 Snapshot Schema:11 个进入字段 / 3 个执行时查询字段 / 7 个禁止字段
  • 冻结了 Output Schema:10 个字段,确认 5 个被业务消费(score/summary/strengths/weaknesses/suggestions),5 个未被消费(blindSpots/clarityLevel/isBeginnerFriendly/analogyQuality/jargonUsage)
  • 冻结了副作用矩阵:6 个副作用(AiAnalysisResult/FocusItem/ReviewCard/UsageLog/ReviewLog/EventBus)及各自的创建条件、数量、失败策略
  • 冻结了 Artifact 矩阵:3 个 Artifact 类型(AiAnalysisResult/FocusItem/ReviewCard)
  • 冻结了幂等契约:feynman:<submissionId> 格式,及 7 项幂等语义
  • 冻结了状态映射表:Legacy(pending/processing/completed/failed)↔ Unified(queued/running/succeeded/failed/cancelled)
  • 冻结了 Job Type 映射:旧 feynman-evaluation → 新 Registry Key feynman_evaluation
  • 冻结了 Feature Flag 契约:FEYNMAN_ENGINE_MODE(legacy/unified)+ 白名单能力
  • 冻结了 FocusItem 创建契约:触发条件、数量、字段映射(含 knowledgeBaseId=unknown bug 修复)
  • 冻结了 ReviewCard 创建契约:选择方案 A(Projector 不包含 ReviewCard,保留异步 EventBus 生成)
  • 冻结了 Projector 原子性边界:事务内 7 步 + 失败回滚语义
  • 冻结了入口兼容契约:请求体字段、响应格式、状态码
  • 冻结了回滚流程:4 步切换 + 4 个不需要
  • 标记了 7 个不确定项(U-1 至 U-7)
  • 绘制了当前时序图和目标时序图
  • 附录列出了 28 个相关文件的精确路径和关键行号

关键发现

  1. FocusItem 的 knowledgeBaseId 永远为 unknownai-analysis.worker.ts:89 使用 result.knowledgeBaseId || 'unknown',但 Feynman Schema 无此字段(Bug,Unified 修复)
  2. FocusItem 创建无结构化数据:Feynman Schema 的 weaknesses 是字符串数组,无 reason/suggestion/priority(与 Active Recall 的结构化 focusItems 不同)
  3. ReviewCard 通过二次 AI 调用生成ReviewCardSubscriberReviewCardGenerationWorkflow(tier: cheap),非从 Feynman 结果直接映射
  4. 旧链路无原子性和幂等性:Result/FocusItem/ReviewCard 在独立操作中写入,无事务保证
  5. 新引擎无 Feynman DefinitionJobDefinitionRegistry 只注册了 active_recall,Feynman 完全走旧路径

修改文件

  • docs/architecture/m-ai-05-feynman-migration-contract.md(新增,300+ 行)

代码证据

  • 无代码修改(纯审计任务)
  • 所有结论基于以下文件的阅读:
    • src/modules/ai-analysis/ai-analysis.controller.ts:29-43 — Feynman HTTP 入口
    • src/modules/ai-analysis/ai-analysis.service.ts:33-52 — 编排:创建 Job + 入队
    • src/modules/ai-analysis/ai-analysis.repository.ts:17-69 — DB 操作 + Shadow Write
    • src/workers/ai-analysis.worker.ts:32-105 — 旧 Worker:Feynman 执行 + FocusItem 创建 + EventBus
    • src/modules/ai/workflows/feynman-evaluation.workflow.ts:17-44 — AI Gateway 调用
    • src/modules/ai/prompts/schemas/feynman-evaluation.schema.ts:3-14 — Zod Schema
    • src/modules/review/review-card.subscriber.ts:12-51 — EventBus → ReviewCard 生成
    • src/modules/review/review.service.ts:68-98 — 二次 AI 调用 + SM-2 初始化
    • src/modules/focus-items/focus-items.repository.ts:23-47 — FocusItem 创建
    • src/modules/ai-job/active-recall-projector.ts:37-202 — 新引擎 Projector 参考实现
    • prisma/schema.prisma:568-757 — 相关数据表结构

测试情况

  • 已运行命令:
    • npx jest --testPathPatterns="ai-job" --passWithNoTests
  • 结果:
    • 13 suites passed, 255 tests passed, 18 skipped, 0 failed
    • 基线确认:无 Feynman 专属单元测试,所有 ai-job 测试通过
    • 无代码修改,无回归风险

未完成 / 风险

  • U-1:submissionId 来源未确认(影响幂等键设计)
  • U-2:knowledgeItemId 不在请求体中(需客户端新增或服务端匹配)
  • U-5:Unified Job 的 attempts 需与 Legacy 对齐(3 次)
  • U-7:FocusItem knowledgeBaseId 修复的兼容性影响待确认

是否建议进入 Review

  • 是 — 契约文档已完整冻结,建议 PM/架构审核后启动 M-AI-05-02
## 开发完成评论 ### 完成内容 - 审计了 `POST /api/ai-analysis/feynman` 的完整 Legacy 调用链(Controller → Service → Queue → Worker → Workflow → Gateway → Provider → Result → FocusItem → ReviewCard) - 冻结了 Snapshot Schema:11 个进入字段 / 3 个执行时查询字段 / 7 个禁止字段 - 冻结了 Output Schema:10 个字段,确认 5 个被业务消费(score/summary/strengths/weaknesses/suggestions),5 个未被消费(blindSpots/clarityLevel/isBeginnerFriendly/analogyQuality/jargonUsage) - 冻结了副作用矩阵:6 个副作用(AiAnalysisResult/FocusItem/ReviewCard/UsageLog/ReviewLog/EventBus)及各自的创建条件、数量、失败策略 - 冻结了 Artifact 矩阵:3 个 Artifact 类型(AiAnalysisResult/FocusItem/ReviewCard) - 冻结了幂等契约:`feynman:<submissionId>` 格式,及 7 项幂等语义 - 冻结了状态映射表:Legacy(pending/processing/completed/failed)↔ Unified(queued/running/succeeded/failed/cancelled) - 冻结了 Job Type 映射:旧 `feynman-evaluation` → 新 Registry Key `feynman_evaluation` - 冻结了 Feature Flag 契约:`FEYNMAN_ENGINE_MODE`(legacy/unified)+ 白名单能力 - 冻结了 FocusItem 创建契约:触发条件、数量、字段映射(含 knowledgeBaseId=unknown bug 修复) - 冻结了 ReviewCard 创建契约:选择方案 A(Projector 不包含 ReviewCard,保留异步 EventBus 生成) - 冻结了 Projector 原子性边界:事务内 7 步 + 失败回滚语义 - 冻结了入口兼容契约:请求体字段、响应格式、状态码 - 冻结了回滚流程:4 步切换 + 4 个不需要 - 标记了 7 个不确定项(U-1 至 U-7) - 绘制了当前时序图和目标时序图 - 附录列出了 28 个相关文件的精确路径和关键行号 ### 关键发现 1. **FocusItem 的 knowledgeBaseId 永远为 unknown**:`ai-analysis.worker.ts:89` 使用 `result.knowledgeBaseId || 'unknown'`,但 Feynman Schema 无此字段(Bug,Unified 修复) 2. **FocusItem 创建无结构化数据**:Feynman Schema 的 weaknesses 是字符串数组,无 reason/suggestion/priority(与 Active Recall 的结构化 focusItems 不同) 3. **ReviewCard 通过二次 AI 调用生成**:`ReviewCardSubscriber` → `ReviewCardGenerationWorkflow`(tier: cheap),非从 Feynman 结果直接映射 4. **旧链路无原子性和幂等性**:Result/FocusItem/ReviewCard 在独立操作中写入,无事务保证 5. **新引擎无 Feynman Definition**:`JobDefinitionRegistry` 只注册了 `active_recall`,Feynman 完全走旧路径 ### 修改文件 - `docs/architecture/m-ai-05-feynman-migration-contract.md`(新增,300+ 行) ### 代码证据 - 无代码修改(纯审计任务) - 所有结论基于以下文件的阅读: - `src/modules/ai-analysis/ai-analysis.controller.ts:29-43` — Feynman HTTP 入口 - `src/modules/ai-analysis/ai-analysis.service.ts:33-52` — 编排:创建 Job + 入队 - `src/modules/ai-analysis/ai-analysis.repository.ts:17-69` — DB 操作 + Shadow Write - `src/workers/ai-analysis.worker.ts:32-105` — 旧 Worker:Feynman 执行 + FocusItem 创建 + EventBus - `src/modules/ai/workflows/feynman-evaluation.workflow.ts:17-44` — AI Gateway 调用 - `src/modules/ai/prompts/schemas/feynman-evaluation.schema.ts:3-14` — Zod Schema - `src/modules/review/review-card.subscriber.ts:12-51` — EventBus → ReviewCard 生成 - `src/modules/review/review.service.ts:68-98` — 二次 AI 调用 + SM-2 初始化 - `src/modules/focus-items/focus-items.repository.ts:23-47` — FocusItem 创建 - `src/modules/ai-job/active-recall-projector.ts:37-202` — 新引擎 Projector 参考实现 - `prisma/schema.prisma:568-757` — 相关数据表结构 ### 测试情况 - 已运行命令: - `npx jest --testPathPatterns="ai-job" --passWithNoTests` - 结果: - 13 suites passed, 255 tests passed, 18 skipped, 0 failed - 基线确认:无 Feynman 专属单元测试,所有 ai-job 测试通过 - 无代码修改,无回归风险 ### 未完成 / 风险 - U-1:`submissionId` 来源未确认(影响幂等键设计) - U-2:`knowledgeItemId` 不在请求体中(需客户端新增或服务端匹配) - U-5:Unified Job 的 `attempts` 需与 Legacy 对齐(3 次) - U-7:FocusItem knowledgeBaseId 修复的兼容性影响待确认 ### 是否建议进入 Review - 是 — 契约文档已完整冻结,建议 PM/架构审核后启动 M-AI-05-02
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/api-server#304
No description provided.