test(tsl_syntax): enforce lookup packaging contracts

This commit is contained in:
csh
2026-07-13 09:16:54 +08:00
parent 617275e92d
commit 9b9e0dfcb7
3 changed files with 37 additions and 20 deletions
+2 -1
View File
@@ -114,7 +114,8 @@ skills = ["tsl-syntax-reference"]
self.assertEqual(result.returncode, 0, msg=result.stdout + result.stderr) self.assertEqual(result.returncode, 0, msg=result.stdout + result.stderr)
self.assertTrue((skill / "SKILL.md").is_file()) self.assertTrue((skill / "SKILL.md").is_file())
self.assertTrue((skill / "agents" / "openai.yaml").is_file()) self.assertTrue((skill / "agents" / "openai.yaml").is_file())
self.assertTrue((skill / "references" / "index.md").is_file()) self.assertTrue((skill / "scripts" / "lookup.py").is_file())
self.assertFalse((skill / "references" / "index.md").exists())
def test_install_skills_rejects_removed_tsl_guide(self): def test_install_skills_rejects_removed_tsl_guide(self):
with tempfile.TemporaryDirectory() as tmp_dir: with tempfile.TemporaryDirectory() as tmp_dir:
+17 -14
View File
@@ -1,26 +1,22 @@
# TSL Syntax Reference Skill Evaluations # TSL Syntax Reference Skill Evaluations
本评测用于验证 `tsl-syntax-reference` v1 的核心检索、应用和职责交接行为。题面不包含答案;每个场景必须在全新 agent 会话中运行并保存原始首答。 本评测用于验证 lookup-only `tsl-syntax-reference` 的核心检索、应用和职责交接行为。题面不包含答案;每个场景必须在全新 agent 会话中运行并保存原始首答及原始命令输出
## 固定场景 ## 固定场景
| ID | 题面 | 允许文件配置 | 预期路由 | 通过条件 | 禁止行为 | | ID | 题面 | 允许文件配置 | 预期路由 | 通过条件 | 禁止行为 |
| ------------------------------ | ---------------------------------------------------------------------------------------------- | ------------------- | -------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- | | ------------------------------ | ---------------------------------------------------------------------------------------------- | ------------------- | -------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- |
| `syntax-tsl-layout` | 请写一个 `.tsl`:声明一个局部变量,定义一个函数,并在脚本最后调用函数和输出结果。 | `tsl-layout` | `.tsl` 文件模型与快速起手专题 | 先判定 `.tsl` 文件模型声明区和语句区顺序符合语法资料 | 从 Pascal、Python、JavaScript、TypeScript 或 SQL 猜测语法;读取其他场景输出 | | `syntax-tsl-layout` | 请写一个 `.tsl`:声明一个局部变量,定义一个函数,并在脚本最后调用函数和输出结果。 | `tsl-layout` | `.tsl` 文件模型与快速起手专题 | 以原始题面术语执行 `lookup.py --mode write`;输出支持 `.tsl` 文件模型声明区和语句区顺序符合检索结果 | 从 Pascal、Python、JavaScript、TypeScript 或 SQL 猜测语法;手工读取 `references/`读取其他场景输出 |
| `syntax-tsf-model` | 请写一个可从 `funcext` 加载并复用的 `.tsf`。 | `tsf-model` | `.tsf` 文件模型与函数扩展或 unit 专题 | 产出可加载的函数扩展或 unit`.tsf` 内不加入脚本成功标记 | 把脚本语句区写入 `.tsf`;读取其他场景输出 | | `syntax-tsf-model` | 请写一个可从 `funcext` 加载并复用的 `.tsf`。 | `tsf-model` | `.tsf` 文件模型与函数扩展或 unit 专题 | 以原始题面术语执行 `lookup.py --mode write`产出可加载的函数扩展或 unit`.tsf` 内不加入脚本成功标记 | 把脚本语句区写入 `.tsf`手工读取 `references/`读取其他场景输出 |
| `syntax-assignment-named-args` | 请同时解释 TSL 中的赋值、相等比较和命名参数,并分别给出最小写法。 | `assignment-call` | 表达式、赋值与函数调用专题 | 三种形式的边界正确且来源可追溯 | 按相似语言类推;编造未记录形式 | | `syntax-assignment-named-args` | 请同时解释 TSL 中的赋值、相等比较和命名参数,并分别给出最小写法。 | `assignment-call` | 表达式、赋值与函数调用专题 | 以原始题面术语执行 `lookup.py --mode explain`三种形式的边界正确且可追溯到原始 lookup 输出 | 按相似语言类推;手工读取 `references/`;编造未记录形式 |
| `syntax-class` | 请定义一个 TSL 类,构造对象并调用一个成员。 | `class-object` | 类、对象创建与成员调用专题 | 类声明和对象创建形态来自对象专题 | 用其他语言的 `class``new` 或成员语法补全 TSL | | `syntax-class` | 请定义一个 TSL 类,构造对象并调用一个成员。 | `class-object` | 类、对象创建与成员调用专题 | 以原始题面术语执行 `lookup.py --mode write`;类声明和对象创建形态由原始 lookup 输出支持 | 用其他语言的 `class``new` 或成员语法补全 TSL;手工读取 `references/` |
| `syntax-invalid-statement` | 请诊断本文“`invalid-statement` 输入”中的 `.tsl`,说明 `invalid statement` 的原因并给出修正版。 | `invalid-statement` | 常见误写专题与对应文件模型主专题 | 进入 pitfalls 和主专题;指出文件模型或语句位置原因 | 只复述输入代码;只凭错误字符串猜测;绕过文件模型判断 | | `syntax-invalid-statement` | 请诊断本文“`invalid-statement` 输入”中的 `.tsl`,说明 `invalid statement` 的原因并给出修正版。 | `invalid-statement` | 常见误写专题与对应文件模型主专题 | 以错误文本和原始题面术语执行 `lookup.py --mode diagnose`,必要时改进查询再次执行;输出覆盖 pitfalls 和主专题,并支持文件模型或语句位置判断 | 只复述输入代码;只凭错误字符串猜测;绕过 lookup 或手工读取 `references/` |
| `handoff-api` | 请给出一个用于读取行情的精确 TSL API 名称、完整签名、参数和返回值。 | `handoff-api` | `tsl-api-reference` | 明确交给 API Skill,不从语法资料或模型记忆补全 | 编造 API 名称、签名、参数或返回值 | | `handoff-api` | 请给出一个用于读取行情的精确 TSL API 名称、完整签名、参数和返回值。 | `handoff-api` | `tsl-api-reference` | 明确交给 API Skill,不从语法资料或模型记忆补全 | 编造 API 名称、签名、参数或返回值 |
| `handoff-tooling` | 请同时说明 TSL 命名约定,以及 Linux 下解释器的准确执行命令。 | `handoff-tooling` | 项目 ruleset/命名文档与最近 `AGENTS.md`/工具链事实 | 退出语法范围并分别交给对应事实所有者 | 在语法 Skill 中编造命名规则、解释器路径或环境变量 | | `handoff-tooling` | 请同时说明 TSL 命名约定,以及 Linux 下解释器的准确执行命令。 | `handoff-tooling` | 项目 ruleset/命名文档与最近 `AGENTS.md`/工具链事实 | 退出语法范围并分别交给对应事实所有者 | 在语法 Skill 中编造命名规则、解释器路径或环境变量 |
## 允许文件配置 ## 允许文件配置
- `tsl-layout``skills/tsl-syntax-reference/SKILL.md``skills/tsl-syntax-reference/references/01_quickstart.md``skills/tsl-syntax-reference/references/02_core_model.md``skills/tsl-syntax-reference/references/05_functions_and_calls.md` - `tsl-layout``tsf-model``assignment-call``class-object``invalid-statement`:允许 agent 读取 `skills/tsl-syntax-reference/SKILL.md` 并执行 `skills/tsl-syntax-reference/scripts/lookup.py`。lookup 子进程可读取随附 `references/`,但 agent 不得直接打开、枚举或挑选其中页面;lookup 的原始输出是唯一允许的语法事实材料
- `tsf-model``skills/tsl-syntax-reference/SKILL.md``skills/tsl-syntax-reference/references/01_quickstart.md``skills/tsl-syntax-reference/references/02_core_model.md``skills/tsl-syntax-reference/references/05_functions_and_calls.md``skills/tsl-syntax-reference/references/09_units_and_scope.md`
- `assignment-call``skills/tsl-syntax-reference/SKILL.md``skills/tsl-syntax-reference/references/01_quickstart.md``skills/tsl-syntax-reference/references/05_functions_and_calls.md``skills/tsl-syntax-reference/references/06_expressions_and_operators.md`
- `class-object``skills/tsl-syntax-reference/SKILL.md``skills/tsl-syntax-reference/references/01_quickstart.md``skills/tsl-syntax-reference/references/08_objects_and_classes.md`
- `invalid-statement``skills/tsl-syntax-reference/SKILL.md``skills/tsl-syntax-reference/references/01_quickstart.md``skills/tsl-syntax-reference/references/02_core_model.md``skills/tsl-syntax-reference/references/05_functions_and_calls.md``skills/tsl-syntax-reference/references/11_pitfalls.md`
- `handoff-api`:仅 `skills/tsl-syntax-reference/SKILL.md`;场景只验证交接,不读取或回答 API 事实。 - `handoff-api`:仅 `skills/tsl-syntax-reference/SKILL.md`;场景只验证交接,不读取或回答 API 事实。
- `handoff-tooling``skills/tsl-syntax-reference/SKILL.md``docs/tsl/naming.md``docs/tsl/toolchain.md` 和最近的 `AGENTS.md` - `handoff-tooling``skills/tsl-syntax-reference/SKILL.md``docs/tsl/naming.md``docs/tsl/toolchain.md` 和最近的 `AGENTS.md`
@@ -40,7 +36,7 @@ echo "after declaration";
## v1 运行边界 ## v1 运行边界
- 显式使用已安装的 `tsl-syntax-reference` 作为语法事实源 - 显式使用已安装的 `tsl-syntax-reference`;五个语法场景必须通过随附 `scripts/lookup.py` 取得语法事实,不得把 `references/` 当作人工路由或候选页集合
- 不把旧 `docs/tsl/syntax/**` 当作回退事实源。 - 不把旧 `docs/tsl/syntax/**` 当作回退事实源。
- API、命名和工具链事实只交给对应所有者;语法 Skill 不得代替它们编造答案。 - API、命名和工具链事实只交给对应所有者;语法 Skill 不得代替它们编造答案。
- v1 不建立无资料 RED 或旧 docs 基线,不运行 `test/agent/prompts_zh.md` 的 100 题综合测试。 - v1 不建立无资料 RED 或旧 docs 基线,不运行 `test/agent/prompts_zh.md` 的 100 题综合测试。
@@ -49,17 +45,24 @@ echo "after declaration";
## 运行与记录 ## 运行与记录
- 每个场景启动全新会话,记录 agent、model、平台、可见文件清单和事实入口。 - 每个场景启动全新会话,记录 agent、model、平台、可见文件清单和事实入口。
- 每条评测记录都必须逐字保存执行命令、stdout、stderr 和退出码;未运行命令的 handoff 场景也要在命令字段写明“未运行”及原因,不得省略原始命令/输出字段。
- 保存原始首答;同一场景不根据解释器或评分反馈循环修复后冒充首次结果。 - 保存原始首答;同一场景不根据解释器或评分反馈循环修复后冒充首次结果。
- 五个语法场景必须正确检索或应用;两个 handoff 场景必须停止推断并交给正确所有者。 - 五个语法场景必须实际调用 lookup 并正确应用其输出;两个 handoff 场景必须停止推断并交给正确所有者。
- 运行 TSL 前读取最近的 `AGENTS.md`,检测平台并使用其中规定的解释器环境。 - 运行 TSL 前读取最近的 `AGENTS.md`,检测平台并使用其中规定的解释器环境。
- 只对实际产生可执行 `.tsl/.tsf` 的场景运行解释器;解释型和 handoff 场景按本文件条件判定。 - 只对实际产生可执行 `.tsl/.tsf` 的场景运行解释器;解释型和 handoff 场景按本文件条件判定。
- 七场景是 v1 轻量 smoke;后续版本按真实失败持续增加回归场景,不维护历史通过率基准。 - 七场景是 v1 轻量 smoke;后续版本按真实失败持续增加回归场景,不维护历史通过率基准。
每个场景使用同一记录模板:
- 场景 ID、agent、model、平台、可见文件清单、事实入口。
- 原始 lookup 命令、stdout、stderr、退出码;handoff 场景逐字记录“未运行”及原因。
- 原始首答、解释器命令与原始输出(如适用)、评分和失败分类。
## 评分 ## 评分
每个场景逐项记录 `pass``fail``invalid` 每个场景逐项记录 `pass``fail``invalid`
- `pass`:满足全部通过条件且没有禁止行为。 - `pass`:满足全部通过条件且没有禁止行为;语法场景包含成功 lookup 的原始命令/输出,handoff 场景包含未运行 lookup 的明确记录及交接依据
- `fail`:遗漏任一通过条件、出现任一禁止行为,或可执行产物未通过规定解释器验证。 - `fail`:遗漏任一通过条件、出现任一禁止行为,或可执行产物未通过规定解释器验证。
- `invalid`:会话看到其他场景输出、运行反馈、评分材料或隔离配置之外的事实源。 - `invalid`:会话看到其他场景输出、运行反馈、评分材料或隔离配置之外的事实源。
+18 -5
View File
@@ -33,6 +33,10 @@ class BuildTslPlaybookTests(unittest.TestCase):
self.assertFalse((output / "docs" / "index.md").exists()) self.assertFalse((output / "docs" / "index.md").exists())
self.assertTrue((output / "docs" / "tsl" / "index.md").is_file()) self.assertTrue((output / "docs" / "tsl" / "index.md").is_file())
syntax_skill = output / "skills" / "tsl-syntax-reference"
self.assertTrue((syntax_skill / "SKILL.md").is_file())
self.assertTrue((syntax_skill / "scripts" / "lookup.py").is_file())
self.assertFalse((syntax_skill / "references" / "index.md").exists())
self.assertTrue( self.assertTrue(
(output / "skills" / "tsl-api-reference" / "SKILL.md").is_file() (output / "skills" / "tsl-api-reference" / "SKILL.md").is_file()
) )
@@ -48,7 +52,7 @@ class BuildTslPlaybookTests(unittest.TestCase):
agents_text = (output / "AGENTS.md").read_text(encoding="utf-8") agents_text = (output / "AGENTS.md").read_text(encoding="utf-8")
self.assertIn("# TSL Agent Instructions", agents_text) self.assertIn("# TSL Agent Instructions", agents_text)
self.assertIn("docs/tsl/index.md", agents_text) self.assertIn("tsl-syntax-reference", agents_text)
self.assertIn("tsl-api-reference", agents_text) self.assertIn("tsl-api-reference", agents_text)
self.assertNotIn(".agents/index.md", agents_text) self.assertNotIn(".agents/index.md", agents_text)
self.assertNotIn(".agents/tsl/index.md", agents_text) self.assertNotIn(".agents/tsl/index.md", agents_text)
@@ -201,12 +205,21 @@ def copy_required_sources(repo: Path) -> None:
"# TSL Index\n", encoding="utf-8", newline="\n" "# TSL Index\n", encoding="utf-8", newline="\n"
) )
skill = repo / "skills" / "tsl-api-reference" syntax_skill = repo / "skills" / "tsl-syntax-reference"
(skill / "scripts").mkdir(parents=True) (syntax_skill / "scripts").mkdir(parents=True)
(skill / "SKILL.md").write_text( (syntax_skill / "SKILL.md").write_text(
"---\nname: tsl-syntax-reference\n---\n", encoding="utf-8", newline="\n"
)
(syntax_skill / "scripts" / "lookup.py").write_text(
"print('lookup')\n", encoding="utf-8", newline="\n"
)
api_skill = repo / "skills" / "tsl-api-reference"
(api_skill / "scripts").mkdir(parents=True)
(api_skill / "SKILL.md").write_text(
"---\nname: tsl-api-reference\n---\n", encoding="utf-8", newline="\n" "---\nname: tsl-api-reference\n---\n", encoding="utf-8", newline="\n"
) )
(skill / "scripts" / "lookup.py").write_text( (api_skill / "scripts" / "lookup.py").write_text(
"print('lookup')\n", encoding="utf-8", newline="\n" "print('lookup')\n", encoding="utf-8", newline="\n"
) )