🐛 fix(tsl-syntax-reference): keep skill self-contained

This commit is contained in:
csh
2026-08-20 16:03:00 +08:00
parent 77ab8211b1
commit 59e40a85a2
2 changed files with 45 additions and 29 deletions
+16 -24
View File
@@ -1,6 +1,6 @@
--- ---
name: tsl-syntax-reference name: tsl-syntax-reference
description: "当用户需要编写、修改、审查或解释 TSL/TSF、TS-SQL、Tinysoft/天软脚本或公式,涉及 `.tsl` / `.tsf` 文件,排查 invalid statement 等语法错误,或核对语言与运行时结构规则时使用;包括你自认为已经确定的写法。不用于查询 API 签名或天软数据字典字段(改用 tsl-api-reference,也不用于选择解释器或运行方式(读取目标文件附近的 AGENTS.md)。" description: "当用户需要编写、修改、审查或解释 TSL/TSF、TS-SQL、Tinysoft/天软脚本或公式,涉及 `.tsl` / `.tsf` 文件,排查 invalid statement 等语法错误,或核对语言与运行时结构规则时使用;包括你自认为已经确定的写法。不用于查询 API 签名或天软数据字典字段,也不用于判断解释器、平台或运行方式。"
--- ---
# TSL Syntax Reference # TSL Syntax Reference
@@ -73,14 +73,14 @@ Section ID 抄自 `--section` 输出首部的 `Section ID:` 行。多个要素
**检索缺口** —— `--query` 改进查询词后仍无匹配;lookup 返回非零状态;`--section` **检索缺口** —— `--query` 改进查询词后仍无匹配;lookup 返回非零状态;`--section`
取回的正文没有支持当前结论;`--section` 正文里目标围栏前没有 `代码块身份:` 行。 取回的正文没有支持当前结论;`--section` 正文里目标围栏前没有 `代码块身份:` 行。
**环境缺口** —— 目标运行时版本不明;项目路径、数据结构或运行参数等项目事实缺失; **范围缺口** —— 请求需要 API 签名、数据字典、解释器或平台可用性、运行结果,或其
`tsl-api-reference` 等依赖的 Skill 不可用 它不属于本 Skill 语法事实的专属知识
缺口时的输出由三部分组成,按此顺序: 缺口时的输出由三部分组成,按此顺序:
1. 已取回并可用的事实,只列 Section ID,不复述正文。 1. 已取回并可用的事实,只列 Section ID,不复述正文。
2. 缺失的具体要素,以及为它试过的查询词。 2. 缺失的具体要素,以及为它试过的查询词。
3. 需要用户提供什么,或需要哪个 Skill、哪份项目文档补齐 3. 需要补齐的具体语法事实,或明确说明该请求超出本 Skill 的范围
不输出包含缺口要素的 TSL 代码,注释掉的、标 TODO 的和「仅供参考」的版本同样不 不输出包含缺口要素的 TSL 代码,注释掉的、标 TODO 的和「仅供参考」的版本同样不
输出。一段代码里只要有一个要素没取回,整段都不给出,不交付「其余部分已验证」的 输出。一段代码里只要有一个要素没取回,整段都不给出,不交付「其余部分已验证」的
@@ -98,31 +98,23 @@ Section ID 抄自 `--section` 输出首部的 `Section ID:` 行。多个要素
本 Skill 只拥有 TSL/TSF 的语言语法、文件模型、表达式、控制流、对象、运行时语言 本 Skill 只拥有 TSL/TSF 的语言语法、文件模型、表达式、控制流、对象、运行时语言
结构和 TS-SQL 外形。混合请求先逐项拆分,只回答其中的语法部分。 结构和 TS-SQL 外形。混合请求先逐项拆分,只回答其中的语法部分。
API 名称、签名、参数、返回值、平台 scope、解释器可用性和金融取数事实属于 API 名称、签名、参数、返回值、平台 scope、解释器可用性、运行结果和金融取数事实
`tsl-api-reference` skill。准备面向用户交付的 TSL/TSF 代码时,按下面顺序处理: 属于本 Skill 的语法事实。准备代码时,先区分语言关键字、用户定义符号和未验证调用;
对未验证调用不声称签名、行为、可用性或输出。代码交付只要依赖这些未验证事实,就按
1. 先枚举代码中除语言关键字和用户定义符号外的调用标识符 「缺口时停止」处理,不能凭参考页示例中的调用名称补齐
2. 语言结构逐项用本 Skill 取回;每个 builtin/API 都逐项用 `tsl-api-reference` 取回
名称、签名和目标 scope。
3. 任一 API 依赖没有取回时,整段交付代码按「缺口时停止」处理;不能只给语法已查的
半成品,也不能凭语法页示例中的 API 名称补齐。
纯语法说明可以使用明确标为占位的用户定义调用来展示调用位置,而不必为该占位符查 纯语法说明可以使用明确标为占位的用户定义调用来展示调用位置,而不必为该占位符查
API;但不得声称该占位调用的 API 行为或输出,也不得把真实 builtin/API 当成无需核对 API;但不得声称该占位调用的 API 行为或输出,也不得把真实 builtin/API 当成无需核对
的占位符。解释一旦包含真实 API 的签名、可用性、返回值输出,或代码将面向用户 的占位符。解释一旦包含真实调用的签名、可用性、返回值输出,就属于本 Skill 未覆盖
交付,就必须执行上面的 API 取回步骤 的事实,按「缺口时停止」处理
## 运行方式不属于本 Skill ## 执行边界
TSL 的运行方式、解释器路径、平台检测和环境选择都不是本 Skill 的事实。用户询问 本 Skill 只检索和解释语法事实,不执行 TSL 代码,也不判断解释器、平台、运行方式或
如何运行 TSL,或需要实际执行 TSL 时,读取目标文件附近最近的 `AGENTS.md`、项目 项目配置。未经执行的代码只能描述为“语法已取回、运行结果未验证”;不得把参考页中的
脚本或 CI,并严格照其规定执行 输出片段当成当前代码的实跑结果
本 Skill 只能确认语法外形正确,不能确认代码在目标解释器上可运行。给出未经执行的
代码时,据此区分「语法已取回」与「运行时未验证」。用户未要求实际执行时,解释器
不可用是受支持状态,不构成事实缺口,也不要求提供可重放运行证据。
## 维护校验 ## 维护校验
维护本 Skill参考页、词表或检索器时,先读 [`data/README.md`](data/README.md),按其中 维护本 Skill参考页、词表或检索器时,只使用随附 `scripts/lookup.py --check` 做结构
的 Section ID、派生规则、粒度和验证纪律执行 校验;命令参数和校验范围以随附脚本的 `--help` 为准
+29 -5
View File
@@ -556,7 +556,7 @@ class TslSyntaxReferenceTests(unittest.TestCase):
self.assertNotIn("<!-- section-id:", output) self.assertNotIn("<!-- section-id:", output)
self.assertNotIn("<!-- quickstart-rule:", output) self.assertNotIn("<!-- quickstart-rule:", output)
def test_skill_contract_uses_extracted_queries_and_deliverable_api_checks(self): def test_skill_contract_uses_extracted_queries_and_scope_checks(self):
skill = SKILL_PATH.read_text(encoding="utf-8") skill = SKILL_PATH.read_text(encoding="utf-8")
help_result = run_lookup("--help") help_result = run_lookup("--help")
self.assertEqual(0, help_result.returncode, help_result.stderr) self.assertEqual(0, help_result.returncode, help_result.stderr)
@@ -567,10 +567,10 @@ class TslSyntaxReferenceTests(unittest.TestCase):
self.assertIn("从用户原话提取", help_text) self.assertIn("从用户原话提取", help_text)
self.assertIn("保留原写法但不传完整用户句", help_text) self.assertIn("保留原写法但不传完整用户句", help_text)
self.assertIn("不传完整用户句", help_text) self.assertIn("不传完整用户句", help_text)
self.assertIn("面向用户交付的 TSL/TSF 代码", skill) self.assertIn("代码交付只要依赖这些未验证事实", skill)
self.assertIn("每个 builtin/API", skill) self.assertIn("不声称签名、行为、可用性或输出", skill)
self.assertIn("纯语法说明", skill) self.assertIn("纯语法说明", skill)
self.assertIn("不得声称该占位调用的 API 行为或输出", skill) self.assertIn("按「缺口时停止」处理", skill)
def test_help_owns_cli_details_and_skill_defers_to_it(self): def test_help_owns_cli_details_and_skill_defers_to_it(self):
skill = SKILL_PATH.read_text(encoding="utf-8") skill = SKILL_PATH.read_text(encoding="utf-8")
@@ -590,7 +590,31 @@ class TslSyntaxReferenceTests(unittest.TestCase):
self.assertIn("构造任一命令前先运行", skill) self.assertIn("构造任一命令前先运行", skill)
self.assertIn("scripts/lookup.py --help", skill) self.assertIn("scripts/lookup.py --help", skill)
self.assertIn("不用于查询 API 签名", skill) self.assertIn("不用于查询 API 签名", skill)
self.assertIn("不用于选择解释器或运行方式", skill) self.assertIn("不用于判断解释器、平台或运行方式", skill)
def test_skill_is_self_contained_and_does_not_reference_host_rules(self):
skill = SKILL_PATH.read_text(encoding="utf-8")
for forbidden in (
"AGENTS.md",
"AGENT_RULES",
".agents/",
"CONTEXT.md",
"memory-bank",
"docs/",
"tsl-api-reference",
"data/README.md",
"项目脚本",
"项目文档",
"CI",
):
with self.subTest(forbidden=forbidden):
self.assertNotIn(forbidden, skill)
self.assertNotRegex(skill, r"\[[^\]]+\]\([^)]*\.md[^)]*\)")
self.assertEqual(
{"SKILL.md"},
set(re.findall(r"[A-Za-z0-9_./-]+\.md", skill)),
)
def test_ci_runs_syntax_structure_and_format_gates(self): def test_ci_runs_syntax_structure_and_format_gates(self):
workflow = CI_PATH.read_text(encoding="utf-8") workflow = CI_PATH.read_text(encoding="utf-8")