# 项目经验总结

更新时间：2026-03-25

这份总结只记录本项目已经真实发生过、并且已经影响工程决策的经验。

## 1. 真正的收口来自证据，不来自感觉

- 只做代码修改，不做完整验证，不能称为收口。
- 这次项目推进中，真正有价值的闭环来自：
  - `go test ./... -count=1`
  - `go vet ./...`
  - `go build ./cmd/server`
  - `cd frontend/admin && npm.cmd run lint`
  - `cd frontend/admin && npm.cmd run build`
  - `cd frontend/admin && npm.cmd run e2e:full:win`

## 2. 浏览器级真实 E2E 与 OS 级自动化不是一回事

- 当前项目已经形成稳定的浏览器级真实 E2E 路径。
- 但这不覆盖系统文件选择器、原生权限弹窗、桌面窗口层行为。
- 因此对外必须区分：
  - 浏览器级真实验证已闭环
  - 完整 OS 级自动化未闭环

## 3. 字符串猜错误类型非常脆弱

- 邮箱验证码限流曾因为错误文本编码漂移，从 `429` 退化成 `500`。
- 短信发送也存在同类风险，甚至一度把限流错误错误映射成 `400`。
- 结论：
  - 错误分级必须优先使用显式错误类型
  - 旧字符串判断只能短期兼容，不能长期依赖

## 4. fake success 比直接失败更危险

- 邮件、短信、OAuth、上传这类链路，如果依赖缺失仍然返回成功，会让前端、测试和运营都得到错误信号。
- 这类问题不会减少故障，只会推迟暴露时间并放大排查成本。
- 结论：
  - 运行时必须 fail closed
  - 缺配置时要么禁用能力，要么启动失败

## 5. 分层设计不是形式问题，而是稳定性问题

- TOTP 服务曾依赖具体仓储实现断言，导致 service 对替换实现和测试 mock 都很脆弱。
- 后续把依赖收回到接口能力后，分层更稳，测试也更自然。
- 结论：
  - service 依赖接口，不依赖具体 repo 类型

## 6. 非测试 `panic` 会放大生产风险

- 兼容入口中的 `panic` 即使当前主路径不用，也会在后续复用、测试或错误调用时变成进程级风险。
- 结论：
  - 非测试代码中的 `panic` 必须持续清零

## 7. `smoke` 可以保留，但必须明确降级

- 诊断脚本有价值，但不能被包装成“主验收已通过”的替代品。
- 结论：
  - `smoke` 只能做补充诊断
  - 主验收必须走真实主链路

## 8. 前端弹窗问题必须被当成缺陷，而不是小瑕疵

- 浏览器原生弹窗会直接打断真实后台主流程和自动化执行。
- 这次项目里，给 `window.alert/confirm/prompt/open` 增加阻断和日志后，验证稳定性明显提高。
- 结论：
  - 原生弹窗和 popup 都应纳入失败信号

## 9. 文档如果不跟着代码一起更新，很快就会反过来误导团队

- 真实状态、规则、发布门槛如果不及时更新，后续协作会不断重复已经踩过的坑。
- 结论：
  - 状态、规则、经验、agent 都要跟代码一起维护

## 10. 接下来仍然属于真实缺口的部分

以下不是"代码没写完"，而是仍未形成完整外部交付证据：

- 真实第三方 OAuth live browser validation
- 外部 Secrets Manager / KMS 证据
- 多环境 CI/CD 密钥分发证据
- 跨历史版本 schema downgrade 回滚证据
- 完整 OS 级自动化证据

## 11. 多智能体并行是提效的关键路径

- 2026-04-02 起，引入 Gitea 远程仓库作为协作基线。
- 后续迭代采用多智能体并行模式：
  - 方案对比阶段：多个智能体并行输出不同方案，由决策者选择最优解。
  - 实现阶段：无依赖的任务并行执行，有依赖的任务按拓扑序执行。
  - 验证阶段：后端测试、前端 lint/build、E2E 测试并行执行。
- 经验教训：
  - 任务拆分必须明确依赖关系，否则并行执行会互相阻塞。
  - 多个智能体修改同一文件时，必须在任务拆分阶段识别并协调。
  - 验证阶段并行执行可以显著缩短反馈周期。

## 12. 方案对比能避免走弯路

- 新增核心功能或架构变更时，必须先做方案对比。
- 对比维度：实现复杂度、性能影响、可维护性、与现有架构的兼容性、测试难度。
- 选定的方案必须记录决策原因，被否决的方案必须记录否决原因。
- 经验教训：
  - 不经过方案对比直接实现，容易在后期发现更优方案，导致返工。
  - 对比记录是团队知识沉淀的重要组成部分。

## 13. 快速迭代的核心是小步验证

- 每个迭代周期不超过 2 小时。
- 每个迭代完成后立即执行验证矩阵。
- 如果验证失败，立即回滚到上一个可用状态。
- 阻塞超过 30 分钟必须上报并寻求协助。
- 经验教训：
  - 大步提交会增加回滚成本和排查难度。
  - 快速验证能尽早发现设计断链和实现偏差。
  - 持续验证比最终验证更可靠。

## 14. 测试全面性决定上线信心

- 新增代码必须有对应测试。
- 修复 bug 必须有回归测试。
- 安全敏感代码必须有边界条件测试。
- 经验教训：
  - 没有测试的代码变更是定时炸弹。
  - 回归测试能防止已修复的问题再次出现。
  - 边界条件测试能发现最隐蔽的缺陷。

## 15. 虚假测试比没有测试更危险

- 虚假测试会给人"已通过"的错觉，推迟问题暴露时间并放大排查成本。
- 项目中发现过的虚假测试模式：
  - 使用 mock 响应替代真实 API 调用进行 E2E 验证
  - 在测试中硬编码预期结果而不走真实业务链路
  - 跳过认证、权限校验等安全环节直接断言页面状态
  - 在测试中使用 `context.Background()` 绕过上下文治理
- 结论：
  - E2E 测试必须启动真实后端进程和前端服务器
  - 必须通过真实浏览器（CDP 协议）执行用户操作
  - 必须验证真实 API 响应和真实数据库状态变化
  - 当前项目的真实 E2E 路径是 `cd frontend/admin && npm.cmd run e2e:full:win`

## 16. 浏览器自动化工具是 E2E 能力的延伸

- Playwright CDP E2E 已经覆盖管理员引导、注册、邮箱激活、登录、认证工作流、响应式布局、桌面/移动端导航。
- 但仍有一些复杂交互场景未被覆盖：
  - 设备信任管理
  - 批量操作
  - 系统设置页
  - 管理员管理页
  - 登录日志导出
- 未来应引入 `agent-browser`（bb browse）等浏览器自动化工具：
  - 补充 Playwright 未覆盖的交互场景
  - 增加复杂业务流程的端到端验证
  - 提供更灵活的用户操作模拟能力
