Files
meida/docs/项目整体评审报告-2026-08-14.md
T
xslandCursor 2934954eb2 按交叉评审对齐文档与代码口径,并挡住 reference 下的密钥文件
表名、配额种子和字段名以产品方案与架构为准;文档仓库补 .gitignore,避免 git add -A 把 API Key 推进远端。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 11:28:35 +08:00

19 KiB
Raw Blame History

「美搭」项目整体评审报告

评审日期:2026-08-14 | 评审人:AI 辅助评审 评审范围:两个仓库全量 —— 文档仓库 G:\meida(13 份文档 + reference 资料)与后端仓库 meida_backend(WSL /home/xsl/meida_backend,HEAD c97f8ae,10 个提交) 评审方法:文档逐份通读 + 后端代码结构/核心模块审查 + 文档 ↔ 代码交叉核对(表名、字段名、种子数据、API 路径、配额数值)+ 对《文档评审报告-2026-08-13》所列 P0 修复项的落地抽查 本文性质:评审反馈,不修改任何被评文档与代码;问题定位到文档章节或代码文件,供修订时对照


0. 总体结论

这个项目的整体质量显著高于同阶段的常见水平,且"自我认知"准确 —— 文档没有夸大、代码没有虚报。主要风险不在工程能力,而在三处:一个躺在工作区里的 API 密钥、一批"文档说改了但代码没改(或反之)"的漂移点、以及既定的内容产能关键路径。

分项结论:

维度 评级 一句话
文档体系 A- 四层结构 + 单一事实源纪律执行到位,上轮评审的 P0 修复抽查全部落地;遗留少量表名/仓库名漂移
后端架构与工程化 A import-linter 四契约、CI 六道防线、迁移往返、双密钥扫描 —— "用机器替 review 守纪律"的做法少见地完整
后端实现完成度 B(符合预期) 工程地基生产级 + 一条真花钱验证过的纵向切片;业务域 9 个包刻意占位,与 Sprint 计划的自我标注(🟡)一致,无虚报
文档 ↔ 代码一致性 C+ 配额种子数据与唯一事实源不符、points_reserved 改名"假回写" 两处必须修;另有若干小漂移
安全卫生 ⚠️ 有一个 P0 reference/deepseek.txt 存有 API 密钥,未被 .gitignore 覆盖,git add -A 即入库

1. 项目现状全景

1.1 文档仓库(G:\meida)

13 份文档构成四层体系(为什么做 → 做什么 → 怎么做 → 谁来做/何时做),7 套编号(FR/NFR/CR/TD/ADR/T/R),README §4.1 建立"单一事实源索引"锁定 13 类关键数字的唯一定义位置。关键业务前提已全部收口:备案已完成(转持续义务)、V1 完全不收费(配额为唯一成本闸门)、素材全部自采(成为新关键路径)、诊断维度 32 项、五行/命理永久不做。

1.2 后端仓库(meida_backend)

层 状态
apps/(api / worker / admin) api ✅(10 个路由,1 条纵向切片)、worker ✅(ping 任务 + 4 队列)、admin 🟦 占位
packages/(20 个包) domain / llm / shared / identity / billing / task / agent ✅ 实现;compliance ⚠️ 仅接口(全 NotImplementedError);kb / memory / notify / profile / report / retrieval / rules / tryon / wardrobe 🟦 占位(README + 空 __init__)
services/(vision / matting / tryon) 🟦 全占位
数据库 2 个迁移:0001 建 8 张表 + pgvector 扩展(向量列未建);0002 给 ob_ai_call 加 tokens_reasoning/rate_tier
测试 142 个测试函数(16 个单测文件 + 1 个集成切片);scripts/smoke.sh 真调 DeepSeek 端到端
工程化 ruff + mypy(domain/llm strict)+ import-linter(4 契约)+ pytest + alembic 往返 + detect-secrets/gitleaks,CI 单 job 六道防线

已打通的真实链路:POST /api/v1/agent/chat → JWT 校验 → 配额预扣(bl_ledger reserved 行)→ 真实调用 DeepSeek(场景路由 / 熔断器 / 峰谷计价 / 思考模式显式关闭)→ 成本行落 ob_ai_call(独立事务)→ 配额 commit / 失败自动 refund。


2. 文档体系评审

2.1 做得好的(应保持)

  1. 单一事实源纪律真的执行了,不只是口号。抽查验证:FR-BILL 引用产品方案 §3.2 而不复述数值;用户系统 §2.4.1 明确"本节不再复述数值";架构 §7.2 token 预算收口 4200/1400 并写明修正原因(原表漏算近轮原文)。
  2. 上轮评审(2026-08-13)的修复可信。抽查 5 项 P0:维度 34→32(架构 §6.2 已改)、可用性 99.9%→99.5%(全库无 99.9% 残留)、人脸保留期 24h→2h(美学报告 §9.1 显式标注废弃原因)、token 两套口径→4200/1400(含错因分析)、流水类型两种→三种(FR-BILL-02 原文更正并留痕)。全部落地。
  3. 风险记录是真实调研出来的,不是模板:腾讯云人体关键点接口下线(2025-10-30)迫使自建 RTMPose、RMBG-2.0 CC BY-NC 许可禁用改 BiRefNet、AI 标识元数据会被 CDN/压缩剥离、DeepSeek 2026-08-17 峰谷涨价(空闲 ¥1.5/¥4.5、高峰 ¥3/¥9 每百万 token)——且都给出了应对与任务编号。
  4. 对代理指标的诚实:明确"预约 ≠ 付费"、V1 不收费意味着付费意愿不可证伪、"配额封不住总成本"的自我纠错(架构 §13 改为三口径)。这类不自欺的表述是文档可信度的来源。
  5. Sprint 计划对已交付部分的验收标注与代码实况相符(🟡 标注诚实,见 §4.3 核对)。

2.2 遗留问题

# 级别 问题 位置 说明
D-1 P1 用户系统文档表名未与架构/代码对齐 用户系统 §2.2、§3.9 仍用 user/user_consent/memory_audit 表名叙述,phone/huawei_open_id 画在主表;而架构 §6.2 与实际代码是 id_user/id_consent/pf_memory_event,手机号在 id_user_identity(phone_enc + phone_hash)。上轮修了枚举与置信度(已对齐),表名这层漏了
D-2 P2 架构 §16.1 仓库根目录写 meida/,实际为 meida_backend 技术架构文档:999 其他文档(任务拆解、Sprint 计划)均已用 meida_backend
D-3 P2 Sprint 计划 §1.1 写"0001 建 9 张表",实际 8 张 Sprint执行计划.md §1.1 迁移文件 op.create_table 计数 = 8
D-4 P2 memory 是 profile 域子模块还是独立包,架构 §4.1 与 §16.1 口径不一 技术架构文档 §4.1 列 11 个业务域(profile 含记忆),§16.1 的 packages 把 profile/ 与 memory/ 列为两个包;实际代码是两个独立包(与 §16.1 一致)。建议在 §4.1 补一句判别口径
D-5 备注 鉴权细节(refresh token 轮换、JWT claims、服务间令牌签发)与 API 限流阈值在文档层仍偏薄 架构 §9/§11 属 T-P1-13 与压测(T-P5-06)范围,开发前需细化

3. 后端代码评审

3.1 做得好的(生产级,保持)

  1. 架构纪律由机器强制,不靠自觉:import-linter 四契约(分层单向、domain 禁框架/IO、业务包禁直连 provider、apps 互不依赖)进 CI;packages/domain 是纯算术(雪花 ID 含时钟回拨处理、配额三段式、任务状态机),mypy strict。
  2. LLM 网关是全仓库最完整的一块,且踩点准确:
    • 峰谷计价赶在 2026-08-17 生效前实现(PeakAwareRateTable 按调用时刻北京时间判档,rate_tier 与 cost_cents 同刻落库,事后不重算);
    • 思考模式显式开关(V4 默认开启,实测开启 13.5s / 关闭 1.8s,思考 token 按输出价计费——四个场景全部显式关闭);
    • 成本行独立事务落库(请求回滚时成本行仍存活)+ Prometheus 双写;
    • prompt 缓存前缀纪律由 validate_cache_prefix() 静态扫描强制(volatile token 检测),strict 模式直接抛错;
    • 4xx 不可重试(避免在备用 provider 烧两次钱)、熔断器三态可注入 clock、结构化输出重试把模型回答带回修正。
  3. 配额三段式正确:reserve/commit/refund + 幂等键派生 + balance_after 流水可重算对账;DeepSeek 超时自动退还配额(集成测试覆盖)。
  4. 错误码体系:4xxxx 客户端 / 5xxxx 服务端 / 6xxxx 外部依赖(把"我们的 bug"与"厂商故障"分开),配额耗尽文案经测试断言不含价格字样(FR-BILL-07 的验收在测试里真实生效)。
  5. 占位是显式的、带启用前置的:智谱 provider 与 compliance 全部 raise NotImplementedError 并注明启用条件(备案覆盖核实、审核+水印+元数据齐备)。"宁可不实现也不半实现"(half-working moderation looks like a working one)这个判断正确。

3.2 代码问题与风险

# 级别 问题 位置 说明与建议
C-1 P1 CI 不跑集成切片 .github/workflows/ci.yml:88 CI 的 pytest 步骤未设 MEIDA_RUN_INTEGRATION=1,而 pytest 默认 -m 'not integration'——集成切片在 CI 里被静默跳过。讽刺的是 CI 明明起了 pgvector + Redis service 容器(目前只服务于 alembic 往返)。建议在 CI 加一步 MEIDA_RUN_INTEGRATION=1 uv run pytest -m integration(容器已就位,零额外成本),否则纵向切片回归只靠本地 make integration
C-2 P1 四档熔断降级未实现,且当前熔断位置与 NFR-COST-02 的退款要求需验证 packages/llm/budget.py 当前只有单一日预算阈值(LLM_DAILY_BUDGET_CENTS)+ critical 场景豁免;60/80/90/100% 四档降级是 T-P1-25b 待补(Sprint 计划已列,属实)。需注意:若 DailyBudgetExceededError 在配额 reserve 之后抛出,必须走 refund——建议给 T-P1-25b 的验收加一条"被拒请求账本净变动 = 0"的集成断言(Sprint §1.2 已写此验收,落实现时别丢)
C-3 P1 日预算阈值未按 8-17 峰谷新价重算 .env.example(LLM_DAILY_BUDGET_CENTS=100000) Sprint §1.3 已自我提醒(输出侧涨 2.25~4.5 倍),此处登记为待办:8-17 之后用实测 token 分布重算,否则熔断会在错误位置触发
C-4 P2 集成测试仅 1 个文件 3 个用例,FakeProvider 替换真实 provider tests/integration/ 真实 provider 行为(超时映射、429、reasoning token 解析)只有单测级的 respx mock 覆盖。可接受,但 C-1 修复后建议补"预算熔断 + 退款"与"幂等键重放"两个集成用例
C-5 P2 ob_ai_call 无保留/归档策略 迁移 0001 成本明细表只增不减,长期需要分区或归档策略(V2 定价依赖它,不能简单清理)。可在架构 §6.2 补一句保留口径
C-6 备注 dev-token 双开关(DEV_AUTH_ENABLED && is_local)设计正确,但上线检查清单应含"确认 prod 无 dev-token 路由" apps/api/routers/auth.py 建议纳入 T-P5 合规检查清单

3.3 与 Sprint 计划自我标注的核对(抽验)

Sprint §1.1 的 🟡 标注与代码实况逐条相符:T-P1-03 确缺 COS mock、T-P1-08 确无 CLS 看板、T-P1-19 确只有 ping 骨架任务、T-P1-26 确无周期重置后台任务(设计上靠 period_key 自然重置,"缺后台"实际指任务奖励发放 bonus 递增链路未建)。没有虚报完成度。


4. 文档 ↔ 代码一致性核对(本次评审的核心增量)

上轮评审只做了"文档 ↔ 文档"比对;本轮首次把实际代码纳入核对。以下按严重程度排列。

4.1 🔴 必须修的漂移

X-1 配额种子数据与"唯一事实源"不符(P0)

README §4.1 与产品方案 §3.2 均声称:bl_quota_rule 的初始化数据一律引用产品方案 §3.2 配额表。但迁移 0001_initial_foundation.py 的种子数据(约 207-235 行)与该表对照:

能力 文档(产品方案 §3.2) 代码种子(bl_quota_rule) 差异
AI 对话 每日 10 轮 / +10 / 硬上限 40 agent_chat: day / 20 / 10 / 50 base 是文档 2 倍,hard 多 10
换装 每日 3 / +3 / 硬上限 8 tryon: day / 3 / 3 / 10 hard 不符(10 vs 8)
报告 首次 1 次(终身);重新生成每 30 天 1 次 / +1 / 每日 ≤ 2 report_basic: month / 1 / 1 / 3 把"首次终身"与"每 30 天重新生成"两个口径揉成一个 key;周期口径(每日 ≤2 vs hard 3)不符
发型/发色试戴 每日 3 / +2 / ≤6 无此 quota_key 缺失
高清导出 每日 1 / — / ≤3 无此 quota_key 缺失
游客配额 换装 1 / 试戴 1 / 报告 1 / 对话 3(设备维度终身) 无承载 缺失(设备维度计量链路未建,V1 骨架可接受,但应显式登记)

处理建议:二选一并留痕——① 按纪律以产品方案 §3.2 为准修正种子(现在表里没有生产数据,改动成本≈0);② 若 20/50 是开发期故意放宽,应通过 bl_quota_rule 的运行时配置覆盖实现(该表本就是配置表),并在文档变更记录登记理由,不能让种子数据成为第二套口径。

X-2 points_reserved → quota_reserved 是"假回写"(P0)

架构文档 v1.3 变更记录与 README §8 均声称已把 tk_task.points_reserved 改名为 quota_reserved(清除 V2"点数"措辞残留,P2-4 修复项)。但实际迁移与 ORM 仍是 points_reserved(migrations/versions/0001_initial_foundation.py:153、packages/shared/models.py)。文档声称与实现相反——要么改代码(推荐,趁表里无数据),要么回退文档表述。

X-3 bl_quota 列名与架构文档不一致(P1)

架构 §6.2/§7.4 明确:bl_quota 列为 used、bonus_granted(物化任务奖励,判定公式 base_limit + bonus_granted);实际代码列为 used、limit_value、bonus_value——名字不同、语义相近,且文档列清单里没有 limit_value、代码里没有文档写的列。任务奖励发放链路(T-P1-26 的剩余部分)实现时会直接撞上这处歧义。

4.2 🟡 核对通过的关键点(列出来给后续评审省时间)

核对项 结论
API 基础路径 /api/v1(规范)+ /v1(别名) ✅ 代码用中间件实现别名,与架构 §9.1 v1.3 澄清一致
表名域前缀(id_/bl_/tk_/ob_) ✅ 代码与架构 §6.2 一致(不一致的是用户系统文档,见 D-1)
流水类型 system_grant/consume/refund 三种 ✅ 代码与 FR-BILL-02 修正后口径一致
ob_ai_call 四列(prompt 版本/思考 token/峰谷档位) ✅ 0002 迁移 + ORM + recorder 均落地,与架构 v1.3 回写一致
峰谷时段(09-12/14-18 北京时间)与单价结构 ✅ cost.py/.env.example 与 Sprint §1.3、架构 §13.2 一致
思考模式四场景显式关闭 ✅ routing.py V1 全 thinking=False,与 T-P1-24a 一致
错误码文案不含价格字样(FR-BILL-07) ✅ 有专项测试断言
日预算 key 按 UTC+8 日滚动 ✅ 与 FR-BILL-01"跨时区按 UTC+8 统一"一致

5. 🔴 安全问题(独立成节,优先级最高)

G:\meida\reference\deepseek.txt 是一个 35 字符的 DeepSeek API 密钥(sk- 开头),当前状态:

  • 未被 git 跟踪,但也未被 .gitignore 覆盖 —— 一次 git add -A && git push 就会把它推到远端;
  • 该仓库已有 remote(origin)。

立即处理(按顺序):

  1. 把该密钥从文件中移除,改放后端 .env(后端仓库的 .gitignore 已正确排除 .env,且 CI 有 detect-secrets + gitleaks 双扫——文档仓库没有这层防护);
  2. 若该密钥已在任何地方暴露过,去 DeepSeek 控制台作废重发;
  3. 在文档仓库加 .gitignore(至少覆盖 reference/*.txt 或明确列该文件);
  4. 顺带清理:reference/ 下的临时资料建议与正式文档分离,避免下次再混入敏感物。

这也暴露一个流程缺口:文档仓库没有 pre-commit/密钥扫描(后端仓库有)。文档仓库虽不含代码,但正是密钥、备案材料这类敏感物容易先落在文档区的地方。


6. 风险总览(按当前时点重排)

风险 等级 现状与依据
密钥泄漏(§5) 🔴 立即 未处理即存在
配额/字段漂移(X-1/X-2/X-3) 🔴 本周 表里尚无生产数据,修错成本每周上升
备案模型清单未核实(T-P0-01) 🔴 既定 README §0.2 第 1 项;影响双路由合法性
内容产能(顾问到岗 + 300 件自采) 🔴 既定关键路径 无新技术判断,按 Sprint §6 倒排执行
8-17 峰谷涨价 🟡 已知 代码已实现峰谷计价;剩"重算日预算阈值"(C-3)
集成回归缺口(C-1) 🟡 CI 容器已就位,修复成本低
四档熔断未实现(C-2) 🟡 T-P1-25b 已列,注意退款验收
算法验证门槛(体型/季型/脸型) 🟡 既定 Sprint 1 结论不达标要换方案,不是硬做

7. 建议行动清单(按优先级)

立即(今天)

  • 处理 reference/deepseek.txt 密钥:移除 + 视暴露情况作废重发 + 补文档仓库 .gitignore

本周(Sprint 0 内)

  • 决策并执行 X-1:以产品方案 §3.2 修配额种子(含补 hairstyle/hd_export 两个 key),或以配置覆盖 + 文档留痕的方式登记偏差
  • X-2:points_reserved → quota_reserved(迁移 + ORM + repo 同步改,趁无数据)
  • C-1:CI 增加 MEIDA_RUN_INTEGRATION=1 pytest -m integration 步骤
  • X-3/D-1:对齐 bl_quota 列名与用户系统文档表名(两处都是"文档 vs 代码"各改一半)

8-17 峰谷生效后

  • C-3:用实测 token 分布重算 LLM_DAILY_BUDGET_CENTS 与四档阈值

随下一轮文档更新

  • D-2(仓库根目录名)、D-3(9→8 张表)、D-4(memory 包归属口径)、C-5(ob_ai_call 保留策略)、C-6(prod 无 dev-token 加入上线清单)

附 A:评审覆盖清单

对象 方式 深度
docs/ 全部 13 份文档 通读(README/评审报告/Sprint/需求规格 §4-5/产品方案 §3.2 逐行;其余 8 份结构化摘要 + 关键节抽读) 中-高
上轮评审 P0 修复项 抽查 5 项(34→32、99.9%、24h、4200/1400、三种流水) 全部落地
meida_backend 全部 10 提交 结构化探索 + 配置/迁移/网关/worker/测试逐模块 中-高
迁移种子数据、字段名、表数 直接读迁移文件逐行核对 高
CI/测试门控 读 ci.yml + Makefile + 测试门控逻辑 高
reference/ 清点(发现密钥文件) 高

未覆盖(后续评审可补):后端单测断言质量逐条审读;.env 实际内容(仅看 example,避免接触真实密钥);鸿蒙端侧代码(尚无仓库);reference/个人形象报告.pdf 内容与美学报告维度字典的映射关系。


评审人:AI 辅助评审(ZCode) 说明:文档侧结论基于文本交叉比对;代码侧结论基于 HEAD c97f8ae。X-1 的配额数值差异存在"开发期有意放宽"的可能解释,需负责人确认意图后二选一处理。