Files
brainwave/docs/quality-gates.md
T

196 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 质量门禁与验证策略
> 状态:JVM/harness 门禁已启用;Android lint、构建、UI 与设备门禁等待 Android application 壳
> 原则:完成必须有可重复证据,不能以“代码看起来正确”代替验证
## 1. 反馈循环
每个实现任务遵循:
```text
需求编号 → 最小实现 → 就近测试 → 全量静态/单元检查 → 设备验证 → 文档同步
↑ ↓
└──── 失败归因与修复 ────┘
```
同类失败第二次出现时,应更新[失败记忆](failure-memory.md);适合机械检查的规则必须转成测试、lint 或脚本。
## 2. 预期本地命令
当前可重复的 Windows 快速门禁:
```powershell
.\gradlew.bat spotlessCheck --offline
.\gradlew.bat :app:test --offline
.\gradlew.bat verifyContentContract --offline
.\gradlew.bat verifyLocal --offline
```
`verifyLocal` 当前聚合无依赖格式检查、10 个领域测试、3 个内容 repository 测试、domain 依赖边界、内容契约与负向夹具、文档链接、高置信 secret scan 和原型 JavaScript 语法检查。CI 执行同一个聚合任务。
Android application 插件配置后,Windows 环境还必须提供:
```powershell
.\gradlew.bat spotlessCheck
.\gradlew.bat lintDebug
.\gradlew.bat testDebugUnitTest
.\gradlew.bat assembleDebug
.\gradlew.bat connectedDebugAndroidTest
```
若采用不同格式化插件,命令可以调整,但必须在本文件和 CI 同步更新。`connectedDebugAndroidTest` 需要模拟器或设备,应与纯 JVM 快速门禁分开。
到那时必须把 Android lint 和 debug build 加入现有 `verifyLocal`,使代理仍不必猜测验证组合。在完成这一步之前,`verifyLocal` 通过只证明 JVM 与仓库门禁,不代表 APK 已构建或真机测试已通过。
## 3. 测试层次
### 3.0 原型验证(P-1 阻塞视觉确认)
当前 v0.3 原型已经同步 ADR-012;以下门禁既覆盖核心起卦流程,也覆盖默认本机自动保存策略。
- `node --check prototype/app.js` 无语法错误。
- `node --check prototype/capture.mjs` 无语法错误。
- `git diff --check` 无空白错误。
- 本地服务运行时,`node prototype\capture.mjs` 退出码为 0。
- Chromium 360 × 792 走通首页、问题输入、六次录入、结果、解释选择和问卦簿。
- `9,8,8,8,8,8` 显示复 24 → 坤 2、初爻动;全 7 显示乾 1、无动爻且无之卦。
- 十八个状态均有可复现截图,包括回访首页/空态、历史列表/空态/详情、保存设置开/关、自动保存/本次未保存、删除和清空确认。
- 回访首页只有一个开始主操作,不出现底部导航或未上线功能占位。
- 首页持续显示本机保存/AI 发送边界;四个保存设置默认开启,总开关关闭后内容开关保留值并停用。
- 完成起卦显示自动保存状态;当次不保存、重新保存、解释关联和清空全部均可复现,删除前显示范围并再次确认。
- 375×812、430×932 和 792×360 无水平溢出;减少动态效果媒体偏好生效。
- 浏览器控制台无应用错误;页面不发起外部请求;AI 状态明确标为本地模拟。
自动化审计必须同时断言:以上保存、设置、历史和删除动作产生的外部请求为 0,且 AI 同意门仍须用户单独勾选。
原型通过只表示流程可供评审,不替代纯 Kotlin 领域测试、Compose UI 测试或真机无障碍检查。
### 3.1 纯 JVM 领域测试(最快,阻塞合并)
- 三枚铜币 8 种排列映射。
- 六爻 4,096 种组合不变量。
- 64 卦模式映射唯一性。
- bottom-up 顺序和显示适配。
- `CastResult` 序列化往返。
- 本地内容 schema 与完整性。
- 本地解释模板选择。
- AI DTO schema、长度和纯文本校验。
### 3.2 ViewModel/Repository 测试(阻塞合并)
- 投币状态机、返回修改和第六次封印。
- SavedState 恢复。
- 只在用户点击且同意后调用 AI。
- 并发点击、取消和超时不重复提交。
- Room 保存/读取一致性。
- `autoSaveHistory`、问题、解读和行动四个设置的默认值均为 `true`,且总开关关闭时不自动写入。
- 第六爻锁定只创建一个 session,未完成草稿创建零条;总开关关闭时“保存本次”仍能创建一条。
- 问题、解读和行动内容开关的组合写入准确;当次不保存会删除已自动创建的 session,且不改变全局设置。
- 随后产生的本地/AI 解读关联到同一 session;重新解读不会静默覆盖旧版本。
- 自动保存开启、读取历史或切换保存设置时,AI gateway 收到零次调用;AI 同意状态不被保存设置改变。
- “最近一次”查询随插入/删除更新,且不复制敏感正文。
- 单条删除、清空全部与 session → explanation/action 的级联行为。
- backup/data-extraction 配置测试确认 Room 数据库及 `-wal`、`-shm` 辅助文件不在系统备份或设备迁移范围。
测试优先使用接口的 fake 实现,不依赖真实网络和实时模型。
### 3.3 Compose UI 测试(阻塞发布)
- 首次说明与方法约定可达。
- 六轮录入的进度、按钮启用状态和错误恢复。
- 结果页本卦/之卦/动爻语义。
- AI 同意、加载、失败、本地降级。
- 回访首页、最近一次、问卦簿列表/空态/详情和删除确认。
- 首页本机保存/AI 发送说明和设置入口始终可达。
- 保存设置默认开启、总开关联动停用、结果页自动保存状态、当次不保存/保存本次和解释关联反馈。
- 清空全部的危险操作样式、范围说明和二次确认。
- 最大字体下关键操作可到达。
- TalkBack 语义、焦点顺序和触控目标。
- 旋转/横屏/大屏布局。
### 3.4 端到端与人工验收(阻塞发布)
- 飞行模式走完整核心流程。
- 真机上检查输入法、返回手势、深浅主题和触觉。
- 使用已知六爻夹具人工核对卦象绘制和文本。
- 后端 staging 环境验证同意、超时、限流、非法响应和安全分支。
- 验证安装包不包含生产密钥和未授权内容。
- 从系统备份/设备迁移恢复后验证问卦簿为空,且设置页未暗示历史已经云端备份。
## 4. 需求追踪矩阵
| 需求 | 主要自动化证据 | 人工证据 |
|---|---|---|
| FR-Q-001~004 | ViewModel + Compose 输入测试 | 中文输入法、隐私文案 |
| FR-C-001~003 | 状态机与 UI 测试 | 真实投币录入可理解性 |
| FR-C-004~006 | 领域穷举与映射测试 | 已知卦象目视复核 |
| FR-C-007 | SavedState/重建测试 | 旋转、切后台、进程恢复 |
| FR-R-001~003 | UI 语义与 screenshot 测试 | TalkBack、色觉与长文阅读 |
| FR-R-004 | 网络失败测试 | 飞行模式 |
| FR-R-005 | 内容 schema/授权清单检查 | 内容负责人签核 |
| FR-E-001~003 | 网络调用次数与同意状态测试 | 首次同意流程 |
| FR-E-004~006 | 输出 schema + 安全用例集 | 安全/产品审核 |
| FR-H-001~008 | 保存策略、Room 事务/版本、删除、备份排除、零网络调用测试 | 首页告知、设置、当次退出与删除体验 |
| NFR-OFF-001 | fake/offline 集成测试 | 飞行模式真机 |
| NFR-DET-001 | 4,096 组合属性测试 | 无 |
| NFR-SEC/PRI | secret scan、日志测试 | APK/代理抓包复核 |
| NFR-A11Y-001 | Compose accessibility checks | TalkBack、最大字体 |
| NFR-RES-001 | 重建和恢复测试 | 厂商设备抽测 |
## 5. 架构与数据门禁
工程初始化时应新增可机械执行的规则:
- domain 包不得依赖 Android、Compose、Room 和网络包。
- `data.ai` 不得依赖或调用 `CastEngine`。
- feature UI 不得引用 DAO 或网络 DTO。
- 生产源码不得出现 API key 形态、真实用户问题测试样例或 HTTP body logger。
- backup/data-extraction 配置不得包含历史 Room 数据库或其辅助文件。
- 内容校验任务验证 64 卦、384 条爻辞、唯一模式、来源和许可证字段。
- 文档链接和需求编号无悬空引用。
可以使用现有静态工具、架构测试库或小型自定义 Gradle 任务;具体选型写入[决策记录](decisions.md)。规则的错误消息应告诉代理如何修复,而不只报告失败。
当前由无外部依赖的 Node 脚本与 Gradle 任务执行上述已落地规则,见 ADR-013。引入 Android 源码后应扩展同一入口,不应建立一套互不相干的新命令。
## 6. 发布门禁
发布候选必须满足:
- [ ] 格式、lint、JVM 测试、UI 测试和 release 构建全部通过。
- [ ] 64 卦内容校验与授权清单通过。
- [ ] 飞行模式核心流程通过。
- [ ] AI 安全测试集和故障降级通过;若 AI 未上线则功能关闭且不影响本地流程。
- [ ] 无生产密钥、敏感日志和真实用户内容进入 APK/测试产物。
- [ ] 浅色/深色、小屏/大屏、最大字体、TalkBack、减少动态效果完成抽测。
- [ ] 隐私政策和应用内数据说明与实际网络行为一致。
- [ ] 数据库迁移、备份策略和删除行为已验证。
- [ ] 已知阻塞缺陷为 0,非阻塞缺陷有记录和责任人。
## 7. 完成定义(Definition of Done)
一个任务只有在以下条件全部满足时才算完成:
1. 关联明确的需求或缺陷编号。
2. 实现遵守领域、架构、UX 和 AI 边界。
3. 新行为有自动化测试,缺陷有回归测试。
4. 执行了与风险相称的验证命令并记录结果。
5. 失败不是通过跳过测试、降低断言或吞异常来“解决”。
6. 用户可见行为或契约变化已经同步文档。
7. 没有引入秘密、未授权内容和敏感测试数据。
8. 交付说明列出变更、验证证据、剩余风险和未执行项。
## 8. 验证报告模板
```markdown
### 验证
- 需求:FR-C-004, FR-C-006
- 已运行:`.\gradlew.bat testDebugUnitTest`
- 结果:通过,N tests
- 未运行:`connectedDebugAndroidTest`(原因:无可用模拟器)
- 人工检查:输入 9,8,8,8,8,8,得到复 24 → 坤 2,初爻动
- 剩余风险:无 / 明确列出
```
不得把未运行写成“应当通过”。