feat(tsl-syntax-reference): harden retrieval and restructure pages

- flag weak candidates (no intent/heading/identifier/tag hit) and exit 2
  when every candidate is weak: mis-hits used to be indistinguishable
  from real hits, so the retry-with-better-terms loop never fired
- accept multiple ids per --section for batch fetch, failing atomically
  on any unknown id so a partial fetch cannot pass as complete
- move query synonyms and page intent aliases to data/lexicon.json and
  enforce alias/page correspondence in --check; curation data no longer
  lives in the engine
- document the weak-hit rule, batch fetch and prelude-once guidance in
  SKILL.md, with curation discipline in data/README.md
- drop 11_pitfalls.md, renumber the trailing pages and spread retrieval
  tags across topics; lexicon keys are page filenames, so the renumbering
  and the new --check rule cannot land in separate commits
This commit is contained in:
csh
2026-07-29 15:45:47 +08:00
parent 37a3bf4b0c
commit 40a9885eb4
28 changed files with 1048 additions and 773 deletions
@@ -6,22 +6,16 @@
回答“目标文件到底是 `.tsl` 脚本还是 `.tsf` 可复用声明文件,以及 `.tsl` 里的哪些内容会顺序执行、哪些内容只是后置声明”。
本页负责文件模型判断;具体语法外形的事实分别见:函数 / 过程 [05_functions_and_calls.md](05_functions_and_calls.md),类 [08_objects_and_classes.md](08_objects_and_classes.md)`unit` / `uses` [09_units_and_scope.md](09_units_and_scope.md),赋值和表达式 [06_expressions_and_operators.md](06_expressions_and_operators.md)。[01_quickstart.md](01_quickstart.md) 只作为最短骨架和高频硬规则速查
## 智能体文件模型判断流程
1. 后缀是第一证据:用户明确要求 `.tsl` 时,按可执行脚本写;用户明确要求 `.tsf` 时,按可复用声明文件写。
2. 没有后缀时看交付目标:入口流程、脚本任务或一次性执行逻辑对应 `.tsl`;可复用交付物(函数、过程、类、模块或扩展文件)对应 `.tsf`;如果只是脚本内部封装函数或类,仍按 `.tsl` 处理。
3. 目标仍不明确时先问用户;不要把脚本入口和可复用模块替用户合并成一个猜测文件。
4.`.tsl` 时,先生成脚本语句区;需要函数、过程或类时,把声明区放在语句区之后。
5.`.tsf` 时,生成顶层函数 / 过程 / 类声明,或 `unit`;不要写成会直接顺序执行的脚本入口。
6. 没有文档证据时不要发明文件模型;只能使用对应专题事实、项目自身文档或项目专属规则,否则记录文档缺口。
本页文件模型的唯一事实源:后缀判断、语句区 / 声明区顺序、`.tsf` 顶层声明形态和文件名约束都在这里收口。函数体、类体、`unit` 内部的语法外形由各自专题页拥有
## 文件模型核心规则
<!-- tags: 该用哪种文件, tsl 还是 tsf, 后缀怎么选, 文件形态判断 -->
- 用户已给出 `.tsl` / `.tsf` 后缀时,后缀就是判断依据;未给后缀时,再按交付目标判断。
- 未给后缀时,入口流程、脚本任务或一次性执行逻辑对应 `.tsl`;可复用交付物(函数、过程、类、模块或扩展文件)对应 `.tsf`;只是脚本内部封装函数或类时,仍按 `.tsl` 处理;仍不明确时向用户确认。
- `.tsl` 脚本按两段理解:语句区在前并按顺序执行;声明区在后,可放 `function / procedure``type Name = class`
- 未给后缀时,入口流程、脚本任务或一次性执行逻辑对应 `.tsl`;可复用交付物(函数、过程、类、模块或扩展文件)对应 `.tsf`;只是脚本内部封装函数或类时,仍按 `.tsl` 处理;仍不明确时向用户确认,不要把脚本入口和可复用模块合并成一个猜测文件
- `.tsl` 脚本按两段理解:语句区在前并按顺序执行;声明区在后,可放 `function / procedure``type Name = class``.tsl` 时先写语句区,需要函数、过程或类时把声明区放在语句区之后。
-`.tsf` 时只写顶层函数 / 过程 / 类声明,或 `unit`;不要写成会直接顺序执行的脚本入口。
- `.tsf` 里的非 `unit` 顶层函数 / 过程可按函数扩展理解:部署到解释器 `funcext` 后,`.tsl` 可以直接调用;顶层类声明只按可复用声明理解;`unit` 按模块组织理解。
- `uses` 可以出现在顶层,但这里只把它当成辅助语句,不把它当成主体声明;函数体和类定义体里的位置限制见 [09_units_and_scope.md](09_units_and_scope.md)。
-`class Name` 不作为类定义写法使用。
@@ -44,6 +38,8 @@
### `.tsl` 文件模型
<!-- tags: 可执行脚本, 顺序执行, 入口脚本, 语句区, 声明区, 脚本从哪开始跑 -->
`.tsl` 脚本语句区的最小形态:
代码块身份:可直接照写示例
@@ -100,6 +96,8 @@ end;
### `.tsf` 文件模型
<!-- tags: 可复用文件, 模块文件, 函数扩展, 别的脚本能调, funcext -->
`.tsf` 顶层函数的最小形态:
代码块身份:可直接照写示例
@@ -119,6 +117,23 @@ end;
1
```
`.tsf` 顶层类声明的最小形态:
代码块身份:可直接照写示例
```tsl
type UserAccount = class
public
Name;
function Describe();
begin
return Name;
end;
end;
```
代码块说明:这个 `.tsf` 只按可复用类声明理解,不会自己顺序执行。文件必须命名为 `UserAccount.tsf`,因为文件名要与第一个顶层声明同名。类成员、可见性和继承的完整事实见 [08_objects_and_classes.md](08_objects_and_classes.md)。
`.tsf` `unit` 的最小形态:
代码块身份:可直接照写示例
@@ -150,7 +165,9 @@ end.
### 文件模型反例
不可照写形态:
<!-- tags: 为什么编译失败, 顶层裸类, 文件写错了, invalid statement -->
顶层裸 `class` 声明:
代码块身份:反例 / 不可照写
@@ -159,7 +176,7 @@ class DemoType
end;
```
上面这种裸 `class` 顶层写法会编译失败。
上面这种裸 `class` 顶层写法会编译失败;顶层类声明必须写成 `type DemoType = class ... end;`
代码块身份:输出片段
@@ -167,22 +184,56 @@ end;
invalid statement
```
## 文件模型归类速查
在声明区之后继续写脚本语句:
任务目标是判断文件属于哪一种模型时,使用下面这组归类:
代码块身份:反例 / 不可照写
- `.tsl` 脚本语句区:直接写会顺序执行的语句。
- `.tsl` 声明区:在语句区之后写 `function ... begin ... end;``procedure ... begin ... end;``type Name = class ... end;`
- `.tsf` 顶层函数 / 过程:写可部署到 `funcext``function` / `procedure` 文件。
- `.tsf` 顶层类声明:写 `type Name = class ... end;`,只按可复用声明理解;类细节见 [08_objects_and_classes.md](08_objects_and_classes.md)。
- `.tsf` 顶层单元:默认先写 `unit ... interface ... implementation ... end.`;简写形态见 [09_units_and_scope.md](09_units_and_scope.md)。
```text
a := 1;
test();
function test();
begin
echo "test";
end;
echo "after declaration";
```
上面最后一行属于「声明区之后继续写脚本语句」,会编译失败。正确做法是把所有会执行的脚本语句都放在声明区之前。
代码块身份:输出片段
```text
Execute script error at Line:9
function:__main__:line 9: invalid statement
```
## 任务到文件模型的选择规则
<!-- tags: 任务对应哪种文件, 起手形态怎么选, 该建什么文件 -->
已经确定任务目标时,按下表选择起手形态:
| 任务 | 起手形态 | 写法 |
| --- | --- | --- |
| 入口流程、脚本任务或一次性执行逻辑 | `.tsl` 脚本语句区 | 直接写会顺序执行的语句 |
| 脚本逻辑需要调用本文件内函数 | `.tsl` 语句区 + 后置函数声明区 | 语句区之后写 `function ... begin ... end;``procedure ... begin ... end;` |
| 脚本逻辑需要对象状态、字段、方法 | `.tsl` 语句区 + 后置类声明区 | 语句区之后写 `type Name = class ... end;` |
| 沉淀可复用函数或过程 | `.tsf` 顶层函数 / 过程 | 写可部署到 `funcext``function` / `procedure` 文件 |
| 沉淀可复用类 | `.tsf` 顶层类声明 | 写 `type Name = class ... end;`,只按可复用声明理解;类细节见 [08_objects_and_classes.md](08_objects_and_classes.md) |
| 把接口和实现组织进一个模块 | `.tsf` `unit` | 默认先写 `unit ... interface ... implementation ... end.`;简写形态见 [09_units_and_scope.md](09_units_and_scope.md) |
补充判断:
- 不要因为代码里需要函数或类就自动升级成 `.tsf``.tsl` 也可以在语句区后放声明区。
- 不要把 `unit` 当成最小起手骨架;只有用户明确要模块接口 / 实现组织,或项目已有 `unit` 边界时,才进入 `unit` 写法。
## 文件模型禁止项
<!-- tags: 不要这样写, 文件模型误用, 两种文件混着写 -->
-`.tsl` 当成 `.tsf` 来写,只给一个顶层函数,不写任何会执行的脚本语句。
- 因为 `.tsl` 脚本内部需要函数或类,就自动改成 `.tsf`
-`.tsf` 当成 `.tsl` 来写,在模块文件里直接堆顺序执行的脚本语句。
-`.tsf` 顶层类声明写成裸 `class Name ... end;`;类声明必须使用 `type Name = class ... end;`
-`uses` 当成主体声明,而不是辅助组织语句。
-`.tsl` 声明区之后继续追加脚本语句。
- `.tsf` 文件名与顶层声明不一致:`UserAccount.tsf` 中写 `function GetUser``type Customer = class``unit CustomerModule` 会导致加载失败或检索混乱。