api-server/docs/architecture/m-ai-05-gate-audit.md
wangdl 8987598eb8 feat(M-AI-05): track Feynman unified engine migration implementation
23 files (+4676/-10):
- Contract: m-ai-05-feynman-migration-contract.md (737 lines)
- Gate audit: m-ai-05-gate-audit.md (318 lines)
- Job Definition + Snapshot Builder + Registration
- Executor + BusinessValidator + ReferenceValidator
- Projector (atomic transaction + 3-layer idempotency)
- ExecutionRouter (FeatureFlag + idempotencyKey)
- ObservabilityService (structured logging + counters)
- Engine: feynman_evaluation execution branch
- AiJobCreationService: feynman_evaluation safety branch
- Controller/Module: Router injection
- CI: path detection for m-ai-05
- E2E: 8 HTTP-layer scenarios (14 total)
- Unit tests: 104 new tests (5 spec files)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 17:44:58 +08:00

8.6 KiB
Raw Blame History

M-AI-05 GATE 独立审核报告

审核日期2026-06-21 角色:独立审核代理(非 M-AI-05 开发执行者) 基线M-AI-04 GATE PASS (92446b9) HEADa532b51


1. Commit 范围

M-AI-04 基线92446b9
M-AI-05 HEADa532b51
Commits
  4f74c09 docs: record P2-06/P2-07 as technical debt
  a532b51 fix(P2-06): remove @Optional() silent skip

M-AI-05 交付物16 untracked files

类别 文件 行数
契约 docs/architecture/m-ai-05-feynman-migration-contract.md 737
Definition feynman-job-definition.ts + spec.ts 77 + 126
Snapshot feynman-snapshot-builder.ts 202
Registration feynman-registration.service.ts 42
Executor feynman-executor.ts + spec.ts 100 + 360
Validator feynman-validator.ts 299
Projector feynman-projector.ts + spec.ts 217 + 391
Router feynman-execution-router.ts + spec.ts 194 + 273
Observability feynman-observability.service.ts + spec.ts 179 + 146
E2E test/m-ai-05-feynman.e2e-spec.ts 521

范围越界检查

检查项 结果
Prisma Schema 修改
新增 Migration
Active Recall 重构
Quiz 迁移
Heavy Runtime 修改
ai-analysis 队列删除
旧 Feynman Worker 删除
客户端接口重构
复习算法重新设计

2. 测试矩阵

测试套件 通过 失败
Feynman Job Definition 26 0
Feynman Executor + Validator 29 0
Feynman Projector 16 0
Feynman Execution Router 14 0
Feynman Observability 19 0
Feynman 合计 104 0
Active Recall (回归) 91 0
总计 195 0

3. 入口与 Feature Flag

3.1 真实入口

POST /api/ai-analysis/feynman  (不变)

调用链:

AiAnalysisController.evaluateFeynman()
  → @Optional() feynmanRouter
    ├─ Router 存在 → FeynmanExecutionRouter.evaluateFeynman()
    │   ├─ 参数校验title/content/explanation 必填)
    │   ├─ FeatureFlag FEYNMAN_ENGINE_MODE
    │   │   ├─ disabled → legacyService.evaluateFeynman()
    │   │   └─ enabled  → Unified 路径
    │   └─ Unified: SnapshotBuilder.build() → AiJobCreationService.createJob()
    └─ Router 不存在 → legacyService.evaluateFeynman()

3.2 分支互斥

检查项 状态
Legacy/Unified 互斥 Router if/else
Unified 失败不 fallback Router catch 不调用 legacyService
无双执行 无同时创建 Legacy + Unified Job
FeatureFlag 默认 legacy 不存在/disabled→false
FeatureFlag 查询失败→legacy catch→return false

3.3 禁止项

禁止项 状态
Controller 直接 BullMQ
直接插入 Outbox 通过 CreationService
绕过 Registry registry.get('feynman_evaluation')
绕过 SnapshotBuilder Router 预构建 Snapshot

4. Definition 与 Snapshot

4.1 Definition

字段 Registry 校验
jobType feynman_evaluation
queueName ai-interactive
timeoutMs 180000
maxRetries 3
promptKey feynman-evaluation
projectorKey feynman_evaluation_projector
credential.allowedModes ['platform_key']

4.2 Snapshot

15 字段:userId, knowledgeItemId, knowledgeItemTitle, knowledgeItemContent, userExplanation, submissionId, knowledgeBaseId, referenceMaterials[], promptKey, promptVersion, modelTier, inputSchemaVersion, outputSchemaVersion, createdAt

  • contentHash 稳定:键排序 + 时间截断到秒
  • 无敏感字段:无 JWT/API Key/Cookie/DB URL
  • prompt/model 值来自 Registry:非硬编码
  • 所有权校验knowledgeItem.userId !== input.userId → ForbiddenException

5. 幂等

5.1 幂等键

feynman:<submissionId>

submissionId 优先级:sessionId:answerId > sessionId > SHA256(title|content|explanation)[:16]

禁止:时间戳、随机 UUID、每次重新生成。

5.2 验证结果

场景 测试
相同 submissionId → 同 jobId E2E 场景 3
只有一个 Snapshot DB count = 1
Projector 重复执行 → 返回已有 Artifact spec
AiAnalysisResult upsert fe_{jobId} deterministic ID
FocusItem findFirst + create spec

6. Executor 与验证

6.1 Executor

职责 状态
仅注入 AiGatewayService
无 PrismaService
消息构造与 Legacy 一致
timeoutMs → AiGateway AbortController

6.2 验证层

覆盖
Zod Schema 10 字段类型/范围/必填
BusinessValidator score[0,100]、clarityLevel 5 枚举、summary 非空、4 数组字段 ≤10×≤500、boolean/enum 检查、代码块检测、模型指令检测
ReferenceValidator URL/email 检测

29 测试覆盖全部验证路径。


7. Projector 与复习产物

7.1 事务原子性

同一 tx 内:AiAnalysisResult (upsert) + FocusItem × N + AiJobArtifact × (1+N)

ReviewCard 按契约 §12 方案 A — EventBus 异步生成(不在事务内)。

7.2 幂等与失败回滚

场景 测试
入口幂等(已有 Artifact→返回
FocusItem findFirst + create 去重
Artifact P2002 幂等
Result 失败 → 后续不执行
FocusItem 失败 → 异常传播

7.3 Bug 修复

字段 Legacy Unified
knowledgeBaseId 恒为 'unknown' 从 Snapshot 读取真实值
knowledgeItemId 未设置 从 Snapshot 读取

8. 权限、状态与安全

8.1 权限

检查项 状态
SnapshotBuilder 校验 knowledgeItem 所有权
E2E 场景 7 跨用户测试 ⚠️ 断言需修正 (201→403)

8.2 状态兼容

Shadow Writepending→queued, processing→running, completed→succeeded, failed→failed

8.3 响应脱敏

不含 internalErrorMessage / validatedOutput / Snapshot / Provider 原始响应 / 堆栈 / Credential。E2E 场景 14 验证。

8.4 BullMQ Payload

{ "jobId": "<AiJob.id>" }

E2E 验证 Object.keys(payload).length === 1


9. 真实运行与 CI

9.1 E2E 场景覆盖

# 场景 HTTP 层 Worker 层
1 Legacy 成功
2 Unified HTTP→Job+Snapshot+Outbox
3 重复提交幂等
4 重复消费幂等 ⚠️ Projector spec
5 重复消费不重复 FocusItem ⚠️ Projector spec
6 重复消费不重复 ReviewCard ⚠️ 方案 A 异步
7 跨用户权限 ⚠️ 断言需修正
8 Unified 失败不 fallback
9 Provider 失败 ⚠️ Engine spec
10 Projector 失败 ⚠️ Projector spec
11 旧查询兼容
12 复习页面查询 ⚠️ Worker 依赖
13 FeatureFlag 回滚
14 错误脱敏

9/14 HTTP 层覆盖5/14 单元测试等效。

9.2 Fail-Closed

  • throw new Error on infra unavailable
  • itIfInfra / soft-pass / || true on test commands
  • CI 触发路径含 test/m-ai-05

10. Legacy 回归

检查项 状态
AiAnalysisWorker 未修改
ai-analysis 队列保留
Legacy Feynman 路径保留
Controller @Optional() fallback
E2E 场景 1/13 验证 Legacy

11. 问题列表

P0

无。

P1

无。 @Optional() Worker 静默跳过已在 a532b51 修复。

P2

ID 问题 影响
P2-01 E2E 场景 7 期望 201 应为 403 权限测试断言不精确
P2-02 Engine if (jobType === 'feynman_evaluation') 4 处 通用 Engine 感知业务 jobType
P2-03 E2E Worker 依赖场景需 CI Docker 本地无法验证

P3

Worker SIGKILL、多 Dispatcher 压测、性能优化。不阻塞。


12. 无法确认项

  1. CI Docker MySQL/Redis 实际就绪状态
  2. E2E Worker 进程全链路执行(需 CI 环境)

13. 最终结论

M-AI-05-GATECONDITIONAL PASS
是否允许进入 M-AI-06是
是否允许生产白名单 Feynman Unified否
是否允许停止 Legacy

升级为 PASS 的条件CI Docker 环境就绪 + E2E Worker 场景通过 + P2-01 修正。