playbook/test/agent/README.md

305 lines
12 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.

# TSL Agent 测试定义
你是 TSL agent 测试执行方。
阅读本 README 后,先向用户询问本机 `tsl` 可执行文件路径。
用户提供路径后,优先自动识别被测 agent 名称;无法可靠识别时,向用户确认一次
agent 短名。随后严格按本文的标准测试流程执行。
轮次边界必须严格执行:
- 第一轮只允许生成首答、落盘、运行验证和记录评分;禁止修复,禁止把运行错误回传给被测 agent禁止修改第一轮结果文件也禁止测试执行方在命令失败后自动编辑文件。
- 本轮计划测试的所有 case 完成第一轮评分后,才允许进入第二轮修复。
- 第二轮只修复第一轮已经记录为 `fail` 的 case每修复某个 case 一次,只增加该 case 的 `repair_count`
这个目录包含 TSL 语法的 agent 测试用例定义。当前评分以运行时验证为准:
生成的 `.tsl``.tsf` 能按标准流程执行通过即为通过,执行报错、超时或文件类型错误即为失败。
## 测试定义
- `prompts_zh.md`:给被测 agent 的题面文件。
- 包含 100 个唯一测试用例。
- 只包含题面,不包含答案、评分细则或 source docs 映射。
- 除非题面明确要求 `.tsf`,默认都要求生成 `.tsl`
不再维护单独的 rubric 文件。不要用人工答案表给被测 agent 提供额外线索。
## 测试产物
所有测试结果都落盘为 `.tsl``.tsf` 文件,不保存 agent 回答 markdown。
- 存放目录:`test/agent/result/<agent>/<YYYYMMDD>/`
- `<agent>` 由测试执行方优先自动识别。
- 识别来源优先使用被测 agent 的产品名、命令名、SDK provider 名或当前运行器已知的 agent 身份。
- 无法从运行器上下文、命令名或已知 provider 可靠识别时,向用户确认一次 agent 短名;不要猜测。
- 目录名统一转成小写短名,只使用 ASCII 字母、数字、短横线、下划线或点。
- 命名格式:
- `.tsl``tsl-001.tsl`
- `.tsf``tsl-037/<TopLevelName>.tsf`
- `.tsf` 调用验证脚本:`tsl-037/verify.tsl`
- 修复轮次按 case 计数:`repair-1/tsl-001.tsl`、`repair-1/tsl-037/<TopLevelName>.tsf`
- 示例:
- `result/claude/20260610/tsl-001.tsl`
- `result/claude/20260610/tsl-037/<TopLevelName>.tsf`
- `result/claude/20260610/tsl-037/verify.tsl`
被测 agent 禁止读取、请求、搜索或引用 `result/`
## 目录结构
```text
test/agent/
├── README.md
├── prompts_zh.md
└── result/
└── claude/
└── 20260610/
├── tsl-001.tsl
├── tsl-037/
│ ├── <TopLevelName>.tsf
│ └── verify.tsl
└── repair-1/
├── tsl-001.tsl
└── tsl-037/
├── <TopLevelName>.tsf
└── verify.tsl
```
## 标准测试流程
### 1. 准备测试
阅读本 README 后,测试执行方必须在开始执行用例前询问并记录本机 `tsl`
可执行文件路径。该路径不写入配置文件,只在本轮运行时验证中使用。
`TSL_HOME` 记为 `tsl` 可执行文件所在目录;如果用户提供的是 TSL 根目录,
则以用户提供的目录作为 `TSL_HOME`
```text
TSL executable path: /path/to/tsl
```
优先自动识别被测 agent 名称并记为 `AGENT`。`AGENT` 不是普通配置项;如果无法从
当前运行器上下文、命令名或已知 provider 可靠识别,则在开始执行用例前向用户确认一次
agent 短名;不要猜测。
```bash
AGENT="<auto-detected-agent>"
DATE=$(date +%Y%m%d)
mkdir -p "test/agent/result/$AGENT/$DATE"
```
### 2. 逐题生成文件
阅读 `prompts_zh.md`,然后按 case 逐题执行测试。
对于每个测试用例:
1. 为当前 case 启动全新的被测 agent 会话。测试执行方可以保持同一个会话,
但被测 agent 不能在同一个会话里连续回答多个 case。
2. 只发送 `prompts_zh.md` 中的 `Runner Setup`、`Answer Rules` 加单个题面,
或只暴露 `prompts_zh.md``docs/index.md` 及其路由到的 `docs/` 子页。
3. 允许 agent 从 `docs/index.md` 自动路由并阅读相关文档。
4. 记录 agent 生成的第一次完整代码并立即落盘。
5. 落盘后冻结该 case 的第一轮结果文件;第一轮不允许 agent 根据运行结果或评分反馈修订答案。
6. 被测 agent 不得主动读取、请求、搜索或引用任何评分材料。
Codex 作为被测 agent 时:
- CLI 自动化:每个 case 单独执行一次 `codex exec`,不要使用 `codex exec resume`
- CLI 自动化如果不想保留会话记录,可使用 `codex exec --ephemeral`
- Codex App 或 IDE每个 case 新建一个 thread不要在同一个 thread 里继续下一个 case。
- Codex SDK/MCP每个 case 调用一次新的 thread/start不要用同一个 thread 连续 run 多个 case。
任何被测 agent 都一样:第一轮运行时验证输出不能回传给被测 agent。第一轮发现错误时
只记录 `fail`,不得修复当前文件,不得让被测 agent 重新回答,不得把修改后的文件计入
第一轮成绩。测试执行方自己的自动修复/纠错行为在第一轮也必须关闭。如果工具在看到
第一轮运行错误后自动修改结果文件,必须按首次落盘文件评分;无法恢复首次落盘文件时,
该 case 标记为 `invalid`。第二轮修复阶段是例外,见“自动修复轮次”。
评分材料包括:
- `result/`
- 运行时验证日志
- 其他 agent 的输出文件
- 对比报告或人工备注
若被测 agent 主动接触评分材料,该 case 或本轮测试应标记为 `invalid`
不计入有效成绩。
推荐的运行器设置:
```text
You are in this repository. The documentation entry point is docs/index.md.
When asked to write TSL, start from docs/index.md and follow its routing to the
relevant TSL pages. Do not infer syntax from Pascal, TypeScript, JavaScript,
Python, or SQL.
```
文件落盘规则:
- 默认每个 case 保存为 `.tsl`,例如 `test/agent/result/<agent>/<YYYYMMDD>/tsl-001.tsl`
- 只有题面明确要求输出 `.tsf` 时,才保存为 `.tsf`,并放入对应 case 目录,
例如 `test/agent/result/<agent>/<YYYYMMDD>/tsl-037/<TopLevelName>.tsf`
- `.tsf` 文件名不能使用 case 编号;文件基名必须与第一个顶层声明同名。
测试执行方应按被测 agent 代码中的第一个顶层声明命名文件,不为了凑文件名改写代码。
- 任何 `unit ... end.` 文件只能保存为 `.tsf`,不能保存为 `.tsl`
- 如果 agent 输出 markdown code fence测试执行方只提取代码内容保存到文件不保存回答 markdown。
### 3. 运行时验证
运行时验证是标准测试流程的一部分。保存 `.tsl``.tsf` 文件后,由测试执行方
逐个验证。第一轮验证必须在被测 agent 会话之外执行,不要把 stdout/stderr 或错误日志
发送回被测 agent即使第一轮发现错误也只记录评分不修复文件。第二轮自动修复阶段
按“自动修复轮次”规则处理。
`.tsl` 验证规则:
```bash
cd test/agent/result/<agent>/<YYYYMMDD>
tsl tsl-001.tsl
tsl tsl-002.tsl
```
`.tsf` 验证规则:
1. 将 case 目录中的 `.tsf` 文件复制到 `TSL_HOME/funcext/tmp/`
2. 在同一个 case 目录中编写 `verify.tsl` 调用脚本。
调用脚本应按被测 agent 实际生成的函数名、unit 名或类型名来调用。
验证脚本必须实际调用 `.tsf` 暴露的功能,不能只输出成功标记。
3. 调用脚本在所有验证调用成功后,用 TSL 输出语句最后输出一行 `__TSL__AGENT__OK__`
4. 执行 `tsl verify.tsl`
5. 验证完成后删除 `TSL_HOME/funcext/tmp/`
```bash
cd test/agent/result/<agent>/<YYYYMMDD>/tsl-037
mkdir -p "$TSL_HOME/funcext/tmp"
cp ./*.tsf "$TSL_HOME/funcext/tmp/"
tsl verify.tsl
rm -rf "$TSL_HOME/funcext/tmp"
```
`funcext/tmp` 由本流程独占。开始验证前不要在该目录保留人工文件;结束后必须清理。
### 4. 第一轮评分规则
- `pass`:按标准流程执行,最后一个非空输出行是 `__TSL__AGENT__OK__`
- `fail`:超时、缺少文件、文件类型错误、`.tsf` 调用脚本失败,
`.tsf` 文件名与第一个顶层声明不一致,`.tsf` 无法被 TSL 加载/编译,
或最后一个非空输出行不是 `__TSL__AGENT__OK__`
- `invalid`:被测 agent 主动读取、请求、搜索或引用评分材料。
TSL 可能在打印错误后仍返回退出码 0因此不能只看 `$LASTEXITCODE`
运行时评分以成功标记为准:脚本没有正常执行到最后,就不会输出最后的
`__TSL__AGENT__OK__`
最终成绩只统计有效 case
```text
pass_rate = pass / (pass + fail)
```
不由被测 agent 自评。
### 5. 自动修复轮次
本轮计划测试的所有 case 完成第一轮评分后,可以对 `fail` 的 case 启动第二轮自动修复。
修复规则:
1. 第一轮期间禁止修复;只有进入第二轮后,第一轮已经记录为 `fail` 的 case 才可以修复。
2. 修复阶段可以把当前文件内容和运行时验证输出发给被测 agent。
3. 每次 agent 产出修复版本,都保存到新的修复目录,不覆盖第一轮文件。
4. 第一次修复保存到 `repair-1/`,第二次修复保存到 `repair-2/`,依此类推。
5. `repair_count` 按 case/file 单独记录;修复 `tsl-019.tsl` 只增加 `tsl-019` 的次数,
不影响其他失败 case。
6. 修复版本仍按同样的运行时验证规则执行,最后一个非空输出行必须是 `__TSL__AGENT__OK__`
示例:
```text
test/agent/result/opencode/20260623/
├── tsl-019.tsl # 第一轮原始输出
├── repair-1/
│ └── tsl-019.tsl # 第 1 次修复
└── repair-2/
└── tsl-019.tsl # 第 2 次修复
```
修复统计:
```text
case_id = tsl-019
first_pass = 第一轮是否 pass
repair_pass = 修复后是否 pass
repair_count = 该 case 的修复版本数量
```
如果第一轮已经 `pass``repair_count = 0`。如果多次修复仍失败,
该 case 的 `repair_count` 记录实际修复次数,`repair_pass = false`。
### 6. 对比分析
不同 agent 的输出直接按目录对比:
```bash
diff -r test/agent/result/claude/20260617 \
test/agent/result/gpt4/20260617
```
建议人工记录汇总表,但不要把汇总表放入被测 agent 可读上下文。
```markdown
| Agent | 测试日期 | 有效用例 | Pass | Fail | Invalid | Pass rate |
|-------|---------|---------:|-----:|-----:|--------:|----------:|
| Claude | 2026-06-17 | 100 | 96 | 4 | 0 | 96% |
| GPT-4 | 2026-06-17 | 100 | 88 | 12 | 0 | 88% |
```
## 版本控制策略
提交到 git
```text
test/agent/README.md
test/agent/prompts_zh.md
```
不提交:
```text
test/agent/result/
```
## 测试用例覆盖
`prompts_zh.md` 包含 100 个测试用例,覆盖:
| 语法点 | 测试用例数 |
| ----------- | ---------- |
| 基础脚本 | 10+ |
| 控制流 | 10+ |
| 函数调用 | 10+ |
| `.tsf`/Unit | 4+ |
| 集合与查询 | 10+ |
| 表达式 | 10+ |
| 类与对象 | 15+ |
| 运行时特性 | 10+ |
| 高级边界 | 10+ |
## 相关文档
- 文档总入口:`docs/index.md`
## 最佳实践
- 测试用例应该对所有 agent 都适用。
- 不要添加特定 agent 的专属测试。
- 关注 TSL 语法本身,而非 agent 特性。
- 每轮测试使用独立日期目录。
- 保留第一次输出作为基线,不根据运行反馈让同一个 agent 修订答案。
- 定期对比不同 agent 的通过率和常见运行错误。
**维护者**TSL Team
**支持的 Agent**:所有支持 TSL 的 agent