---
name: nagi-studio-prove-it
description: "让 agent 拿证据交差，而不是只说一句「做好了」。三种时候用：agent 准备交差时；用户为同一件事第二次纠正 agent（又错了、说过多少遍、怎么让它别再犯）；要写测试、或者清理没用的测试时。prove it、stop repeating this mistake、clean up useless tests。"
license: "MIT"
metadata:
  decimalai-skill-id: "95f55f67-848b-41a1-9f83-619a2cdc9287"
  decimalai-version-id: "6d11d097-e987-4013-959b-5878fa7222d0"
  decimalai-version: "1"
  decimalai-body-sha256: "85d82edeb0e50d4a611cee0cceda8cb485507f7a8831717654f2a6b609599e63"
  decimalai-name: "nagi-studio/prove-it"
  decimalai-format: "1"
  decimalai-invocation: "model"
  decimalai-category: "testing"
  decimalai-source: "https://app.decimal.ai/s/nagi-studio-prove-it@1/SKILL.md"
---
「做好了」不算数，跑过的测试结果和截图才算。

## 交差之前

1. 跑项目的测试命令。现有测试确实测不到这次改动的行为，才补一个，写法见下面「写测试」。修 bug 不用每次都配一个回归测试。
2. 改动用户看得见（网页、界面）：写一个 Playwright 浏览器测试，在真浏览器里把改过的流程点一遍，控制台一报错就算失败，每一步截一张图存进项目。没装浏览器：`npx playwright install chromium`，或者直接用本机 Chrome（`channel: 'chrome'`）。你自己带浏览器工具的话，也可以直接用。
3. 有一项没通过，先修好，修完再交差。
4. 交差按这个格式写：

```
做了什么：一句话
测试：<命令> → 通过 N，失败 0
截图：<路径>
没验证到的：哪些、为什么；没有就写「无」
```

## 被纠正之后

先把这次的错修好。再想一想：下一个 agent 只看它打开的那个文件、照着最近的例子抄、走最短的路，它会不会再犯一遍？会的话，就把这个错拦在它犯之前。

顺手翻一下最近的提交和 AGENTS.md：同类的错以前犯过的，一起拦掉。

拦法从强到弱，前面的用得上就不往后选：

- **让它没地方犯**：一件事只留一个地方负责、一种做法；删掉 agent 会照抄的旧写法；要手动同步的几份清单合成一份。
- **让它一犯就报错**：类型、lint、测试、校验脚本都行。报错信息直接写该改用什么。
- **让人一眼看见**：好不好看、顺不顺手，机器判断不了，就交差时附截图，交给人看。
- **写进 AGENTS.md**：只留给需要判断的事。agent 跳过这种规则，什么都不会报错。

加了一道检查，就拿这次真实犯过的错去试：把错放回去，检查必须报错；改回来，必须通过。从来没报过错的检查，等于没加。

最后在 AGENTS.md 的规则表里记一行：

```
| 规则 | 由什么拦住 |
|---|---|
| 交差前跑通测试，附截图 | `npm test` + 浏览器截图 |
```

这条规则表里本来就有、却没有东西拦住，说明是重犯，这次就往强的那一端提一档。错已经不可能再犯了，就把那一行删掉。

## 写测试

测试只守用户感受得到的行为：存进去的能读出来，点了按钮页面会变。下面三种是垃圾测试，改掉，改不了就删：

- **假装测试**：要守的那部分被测试替身（mock）顶掉了。比如测数据能不能存，连的却是假数据库，真数据库断了它照样通过。
- **自己考自己（tautological）**：标准答案是照着代码现在的输出抄的，代码错了，答案也跟着错。
- **死抠细节（implementation-coupled）**：查的是变量名、某个内部函数调了几次。功能没变，只是换个写法就失败了。

判断办法：把它要守的功能故意弄坏，这个测试应该失败；只给内部变量改个名，它应该照样通过。做不到的，就是垃圾测试。
