12 KiB
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.tslresult/claude/20260610/tsl-037/<TopLevelName>.tsfresult/claude/20260610/tsl-037/verify.tsl
被测 agent 禁止读取、请求、搜索或引用 result/。
目录结构
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。
TSL executable path: /path/to/tsl
优先自动识别被测 agent 名称并记为 AGENT。AGENT 不是普通配置项;如果无法从
当前运行器上下文、命令名或已知 provider 可靠识别,则在开始执行用例前向用户确认一次
agent 短名;不要猜测。
AGENT="<auto-detected-agent>"
DATE=$(date +%Y%m%d)
mkdir -p "test/agent/result/$AGENT/$DATE"
2. 逐题生成文件
阅读 prompts_zh.md,然后按 case 逐题执行测试。
对于每个测试用例:
- 为当前 case 启动全新的被测 agent 会话。测试执行方可以保持同一个会话, 但被测 agent 不能在同一个会话里连续回答多个 case。
- 只发送
prompts_zh.md中的Runner Setup、Answer Rules加单个题面, 或只暴露prompts_zh.md加docs/index.md及其路由到的docs/子页。 - 允许 agent 从
docs/index.md自动路由并阅读相关文档。 - 记录 agent 生成的第一次完整代码并立即落盘。
- 落盘后冻结该 case 的第一轮结果文件;第一轮不允许 agent 根据运行结果或评分反馈修订答案。
- 被测 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,
不计入有效成绩。
推荐的运行器设置:
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 验证规则:
cd test/agent/result/<agent>/<YYYYMMDD>
tsl tsl-001.tsl
tsl tsl-002.tsl
.tsf 验证规则:
- 将 case 目录中的
.tsf文件复制到TSL_HOME/funcext/tmp/。 - 在同一个 case 目录中编写
verify.tsl调用脚本。 调用脚本应按被测 agent 实际生成的函数名、unit 名或类型名来调用。 验证脚本必须实际调用.tsf暴露的功能,不能只输出成功标记。 - 调用脚本在所有验证调用成功后,用 TSL 输出语句最后输出一行
__TSL__AGENT__OK__。 - 执行
tsl verify.tsl。 - 验证完成后删除
TSL_HOME/funcext/tmp/。
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:
pass_rate = pass / (pass + fail)
不由被测 agent 自评。
5. 自动修复轮次
本轮计划测试的所有 case 完成第一轮评分后,可以对 fail 的 case 启动第二轮自动修复。
修复规则:
- 第一轮期间禁止修复;只有进入第二轮后,第一轮已经记录为
fail的 case 才可以修复。 - 修复阶段可以把当前文件内容和运行时验证输出发给被测 agent。
- 每次 agent 产出修复版本,都保存到新的修复目录,不覆盖第一轮文件。
- 第一次修复保存到
repair-1/,第二次修复保存到repair-2/,依此类推。 repair_count按 case/file 单独记录;修复tsl-019.tsl只增加tsl-019的次数, 不影响其他失败 case。- 修复版本仍按同样的运行时验证规则执行,最后一个非空输出行必须是
__TSL__AGENT__OK__。
示例:
test/agent/result/opencode/20260623/
├── tsl-019.tsl # 第一轮原始输出
├── repair-1/
│ └── tsl-019.tsl # 第 1 次修复
└── repair-2/
└── tsl-019.tsl # 第 2 次修复
修复统计:
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 的输出直接按目录对比:
diff -r test/agent/result/claude/20260617 \
test/agent/result/gpt4/20260617
建议人工记录汇总表,但不要把汇总表放入被测 agent 可读上下文。
| 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:
test/agent/README.md
test/agent/prompts_zh.md
不提交:
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