# 规范 · TDD 验收契约 ## 1. 唯一产物 默认只生成: ```text output/tests/TDD验收契约.md ``` 它同时承担完成定义、验收清单和完整 `/goal` 的测试终止条件。它不是完整开发提示词;不得把相同信息复制到测试索引、逐层 TDD、任务图、追溯矩阵或状态 JSON。 ## 2. 一条验收项的颗粒度 一条验收项必须满足: 1. 对应一个用户可观察结果,或一个独立的高影响业务约束。 2. 可以由一次连续操作或一组紧密相关断言验证。 3. 失败时能说明哪种产品能力没有交付。 4. 能引用真实 Source ID、Design ID 或上游产物。 5. 验证成本与风险相称,Coding Agent 能在完整开发循环中实际执行。 不按以下对象拆用例: - 单个函数、组件、字段或断言。 - null、undefined、空字符串等业务后果相同的输入变体。 - 单元/组件/集成/E2E 等技术测试层。 - 为满足“每类至少一条”而虚构的场景。 只有不同分支会造成不同业务后果、需要不同实现或不同修复时才拆开。 ## 3. 来源覆盖 Feature: - 覆盖所有 MVP active REQ。 - 覆盖所有 P0/P1 AC。 - 覆盖所有明确声明且 active 的 NFR;性能、无障碍等只有存在 NFR 或明确风险才进入 required。 - `页面清单.md` 中每个 MVP `PAGE-*` 至少映射到一条 `DESIGN-*` 验收;该行同时写入实际 MD 与 HTML 相对路径,不用通配符或根据页面显示名称猜路径。 Bugfix: - 覆盖 REPRO、CUR、EXP、UNCH、CON 中全部 active 条目。 - 最少包含复现、修复结果和关键不变行为回归;详见 `Bugfix测试与修复规范.md`。 一条场景可以覆盖多个 Source/Design ID。覆盖完整不等于一对一生成用例。 ## 4. 测试预算与压缩闸门 普通 MVP 的行为/风险场景通常为 8–20 条,设计落地按 MVP 页面紧凑列行。 超过 25 条行为/风险场景时,生成 Agent 必须逐条问: 1. 它能捕获其它场景捕获不到的失败吗? 2. 这个失败会影响 MVP 的可用性、正确性或可信度吗? 3. 能否与相同旅程、相同失败后果或相同验证方式的场景合并? 任一答案是否定或可以合并,就删除/合并。复杂项目有真实独立风险时允许超过 25 条,不得为了守数字漏掉关键约束。 ## 5. 必须覆盖的验证面 ### 5.1 冒烟 - 安装/依赖可用。 - 构建或静态检查成功。 - 应用能启动,关键入口可访问。 - 至少一条最核心用户旅程可走通。 - 没有阻断操作的运行时错误。 把紧密连续的启动步骤合成 1–3 条,不为每条命令各建一条。 ### 5.2 功能与流程 - 从 P0/P1 AC 组合核心用户旅程。 - 同时断言页面反馈、业务结果和关键数据变化,避免只断言“请求成功”。 - 一个旅程可以跨多个页面、接口和数据动作。 ### 5.3 设计落地 - 每个 MVP 页面、必要弹窗和会改变用户判断的关键状态均有覆盖。 - 每个 `DESIGN-*` 只对应一个 PAGE ID;通过标准从实际 HTML 提取并明确写出 `结构/组件/内容/交互/视觉/原生适配` 六类锚点,禁止只写“与原型一致”。 - 规范产物位于 `output/pages/` 直属目录,MD/HTML 主文件名相同;TDD 记录实际读取到的两个路径。 - 若名称或目录不规范,先读内容:优先用 MD 页面 ID 与 HTML `meta[name="page-id"]`,旧产物可用页面标题/正文辅助。能唯一匹配同一 PAGE ID 就记录实际路径与警告后继续;零匹配、多匹配或内容冲突才失败。 - 在真实运行页面中操作,不以高保真 HTML 文件存在代替实现。 - 所有 MVP 页面都要在同一内容区尺寸、同一数据和交互状态集下保存原型 `baseline.png` 与成品 `actual.png`;状态集包含正常态及该行明确的弹窗/关键状态,多状态可按相同顺序拼入一张 PNG。 - 独立视觉验收官必须实际查看两张图片,逐项核对结构、组件、内容、交互入口和视觉层级;只看代码、DOM、测试日志或 UI 自动化结果都不算视觉验收。 - 不要求像素级机械相等;缺页、缺区域、组件/数量不符、关键内容缺失、交互入口变化、布局层级走样或原生体验违和必须失败。 - 原生平台适配只能优化窗口外壳、控件反馈和平台操作习惯,不得改变已确认的信息结构、功能和流程。先一致再优化,禁止借“超过原型”自由改版。 ### 5.4 风险触发 只从真实信号触发: | 信号 | required 验收重点 | | :--- | :--- | | 登录、角色、私有资源 | 未登录、水平/垂直越权、会话边界 | | 金额、库存、额度 | 服务端重算、不可篡改、原子性/重复提交 | | 重要或不可逆数据 | 数据完整性、失败不产生半成品、恢复/撤销约束 | | 外部 API/服务 | 关键成功契约、失败反馈、不得重复副作用 | | 明确 NFR | 按 NFR 的指标、阈值、采样与时间窗验证 | 没有上述信号时不生成对应测试。 ## 6. 验证方式 每条只选择足以证明结果的最低成本方式: - 纯业务规则:单元测试。 - API、数据库或外部契约:集成/API 测试。 - 用户旅程、页面联动:浏览器 E2E。 - 页面完整性与视觉:同状态集原型/成品 PNG 截图对 + 独立视觉复核。 - 构建和启动:真实命令与退出码。 TDD master 不预写可执行测试代码,不猜尚不存在的函数、文件、Mock 和失败堆栈。Coding Agent 依据实际代码结构选择测试文件和命令。 ## 7. 去重与质量检查 生成完成后检查: - 每个 required Source ID 至少出现一次。 - 每个 MVP PAGE ID 至少出现一次。 - 每个 `DESIGN-*` 行包含该 PAGE ID 的实际 MD 与 HTML 路径;校验器能读取两份内容并确认身份。非规范命名只警告,不伪报缺失。 - 每条场景有明确动作、可观察结果和验证方式。 - 没有两个场景只是在重复相同失败后果。 - 没有用“页面能打开”“请求成功”“看起来正常”作为完整通过标准。 - 无障碍、性能、安全、边界等没有在缺少需求/风险时被机械加入。 - 契约不复制 PRD/Design,不包含测试框架教程和大段执行纪律。 ## 8. `/goal` 消费与执行结果 契约只定义“要证明什么”,执行期不得把状态或证据回填到契约。完整 `/goal` 在改任何代码前创建唯一运行态文件: ```text output/tests/TDD验收结果.md ``` 文件保持紧凑,先写固定元信息: ```text - contract_sha256: sha256:<当前契约原始字节的 64 位 hex> - run_started_at: <本轮 ISO 8601 时间> ``` 再写一张表: | TDD ID | 状态 | 实际验证动作 | 证据 | | :--- | :--- | :--- | :--- | | `SMOKE-01` | `pending \| pass \| fail` | `本轮真实执行的命令或操作` | `退出码、API 结果或测试汇总` | | `DESIGN-01` | `pending \| pass \| fail` | `独立验收官实际查看 baseline+actual 并看图核对` | `baseline=tests/visual/PAGE-…-baseline.png; actual=tests/visual/PAGE-…-actual.png; reviewer=independent-visual; review=pass; blocking=0` | 执行规则: 1. 开工前提取契约全部验收 ID(`SMOKE/FLOW/DESIGN/RULE/BUG-*`),一项不漏、一项不重,全部初始为 `pending`。 2. 每个纵向切片先声明关联 ID;严格按对应行的验证方式真实执行后,立即更新动作、证据和状态。 3. 只有本轮命令与退出码、API 结果或测试结果能支持功能项 `pass`。代码审查、功能已实现、旧日志、“应该通过”都不是证据。 4. `DESIGN-*` 另需两个不同路径、真实存在且尺寸相同的 PNG,以及 `reviewer=independent-visual; review=pass; blocking=0`。UI 自动化、单张截图、未实际看图或自我验收一律失败。 5. 契约变化时旧台账整体失效;相关实现变化时相关 `pass` 失效并重验、重截、重审。 6. 完成前用脚本或命令机械核对:契约哈希一致、契约 ID 集合与结果 ID 集合完全相等且无重复、`pending=0`、`fail=0`、`pass=总数`,每个 `pass` 的动作和证据有效。 能定位已安装的 tdd-master 时,完成前用同一校验器的结果模式复核: ```text "/validators/check_delivery_contract.py" --result "{项目名}/output" ``` 无法定位校验器时才使用等价脚本机械比对,严禁靠人工目测计数后宣布全绿。 **这是最容易出现假完成的地方:未先建全量台账就写代码、最后一次性倒填、把阻塞项写成 `pass`,都视为 TDD 未执行,不得交付。** ## 9. 与完整 `/goal` 的边界 - 本契约回答“哪些结果必须通过”。 - `TDD验收结果.md` 回答“本轮是否真的逐项证明通过”。 - 营队现有完整 `/goal` 回答“如何准备环境、建立结果台账、实现生产代码、持续验证、修复、提交和交付”。 - 契约内不复制、缩写或替代完整 `/goal`;tdd-master 交付汇报时只提示用户下一步使用现有 `/goal`。