playbook/tests/test_tsl_entrypoints_consis...

620 lines
29 KiB
Python
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.

import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
RULESET_TSL = ROOT / "rulesets" / "tsl" / "index.md"
TSL_INTRODUCTION = ROOT / "docs" / "tsl" / "syntax" / "01_introduction.md"
TSL_QUICKSTART = ROOT / "docs" / "tsl" / "syntax" / "02_quickstart.md"
TSL_CORE_MODEL = ROOT / "docs" / "tsl" / "syntax" / "03_core_model.md"
TSL_VALUES = ROOT / "docs" / "tsl" / "syntax" / "04_values_and_literals.md"
TSL_VARIABLES = ROOT / "docs" / "tsl" / "syntax" / "05_variables_and_constants.md"
TSL_FUNCTIONS = ROOT / "docs" / "tsl" / "syntax" / "06_functions_and_calls.md"
TSL_EXPRESSIONS = ROOT / "docs" / "tsl" / "syntax" / "07_expressions_and_operators.md"
README = ROOT / "README.md"
PLAYBOOK_EXAMPLE = ROOT / "playbook.toml.example"
SKILLS_DOC = ROOT / "SKILLS.md"
TEMPLATES_CI_README = ROOT / "templates" / "ci" / "README.md"
TEMPLATES_README = ROOT / "templates" / "README.md"
REMOVED_TSL_GUIDE = ROOT / "skills" / "tsl-guide"
TSL_REFERENCE_INDEX = ROOT / "docs" / "tsl" / "reference" / "index.md"
TSL_REFERENCE_CATALOG_INDEX = ROOT / "docs" / "tsl" / "reference" / "catalog" / "index.md"
TSL_REFERENCE_VERIFIED_INDEX = ROOT / "docs" / "tsl" / "reference" / "verified" / "index.md"
TSL_REFERENCE_VERIFIED_CORE = ROOT / "docs" / "tsl" / "reference" / "verified" / "core.md"
TSL_REFERENCE_UNAVAILABLE = ROOT / "docs" / "tsl" / "reference" / "unavailable_methods.md"
TSL_FINANCE_INDEX = ROOT / "docs" / "tsl" / "finance" / "index.md"
TSL_MODULES_INDEX = ROOT / "docs" / "tsl" / "modules" / "index.md"
TSL_REMAINING_SYNTAX_AGENT_SECTIONS = {
"08_control_flow.md": "Agent 控制流判断流程",
"09_objects_and_classes.md": "Agent 对象/类判断流程",
"10_units_and_scope.md": "Agent unit/作用域判断流程",
"11_runtime_context_and_with.md": "Agent 运行时上下文判断流程",
"12_pitfalls.md": "Agent 常见误写判断流程",
"13_matrix_and_collections.md": "Agent 矩阵/集合判断流程",
"14_resultset_and_filters.md": "Agent 结果集/过滤判断流程",
"15_ts_sql.md": "Agent TS-SQL 判断流程",
"16_debug_and_profiler.md": "Agent 调试/Profiler 判断流程",
"18_lexical_structure_and_compile_options.md": "Agent 词法/编译选项判断流程",
"19_types_and_conversions.md": "Agent 类型/转换判断流程",
"20_strings_and_text.md": "Agent 字符串/文本判断流程",
"21_external_calls_and_threads.md": "Agent 外部调用/线程判断流程",
"22_namespace_libpath_and_unit_runtime.md": "Agent 命名空间/Libpath 判断流程",
"23_object_runtime_and_introspection.md": "Agent 对象运行时/反射判断流程",
"24_builtin_runtime_objects.md": "Agent 内置运行时对象判断流程",
"25_set_operations.md": "Agent 集合运算判断流程",
"26_matrix_deep_dive.md": "Agent 矩阵深水判断流程",
"27_fmarray.md": "Agent FMArray 判断流程",
"28_ts_sql_core.md": "Agent TS-SQL Core 判断流程",
"29_ts_sql_advanced.md": "Agent TS-SQL Advanced 判断流程",
"30_runtime_services_and_global_cache.md": "Agent 运行时服务/全局缓存判断流程",
"31_complex_and_weakref.md": "Agent 复数/弱引用判断流程",
"32_object_overloads_and_iteration.md": "Agent 对象重载/迭代判断流程",
}
class TslEntrypointsConsistencyTests(unittest.TestCase):
def test_ruleset_lists_canonical_tsl_layers(self):
text = RULESET_TSL.read_text(encoding="utf-8")
self.assertIn("docs/tsl/index.md", text)
self.assertIn("docs/tsl/syntax/index.md", text)
self.assertIn("docs/tsl/finance/index.md", text)
self.assertIn("docs/tsl/modules/index.md", text)
self.assertIn("docs/tsl/reference/index.md", text)
def test_readme_only_lists_two_official_deployment_routes(self):
text = README.read_text(encoding="utf-8")
self.assertIn("方式一git subtree", text)
self.assertIn("方式二:外部 clone 后执行部署", text)
self.assertIn("- `rulesets/typescript/index.md`TypeScript 核心约定", text)
self.assertIn("`project_root`:目标项目根目录", text)
self.assertIn("`playbook_root`:相对于 `project_root` 的项目内 Playbook 根目录", text)
self.assertIn("不是外部 clone 出来的 Playbook 仓库路径", text)
self.assertIn("外部 clone 场景下必须显式填写 `playbook_root`", text)
self.assertNotIn("方式二:手动复制快照", text)
self.assertNotIn("方式三CLI 裁剪复制", text)
self.assertNotIn("如果省略 `playbook_root`,默认仍部署到 `docs/standards/playbook`", text)
def test_playbook_example_defines_playbook_root_as_target_path(self):
text = PLAYBOOK_EXAMPLE.read_text(encoding="utf-8")
self.assertIn('playbook_root = "docs/standards/playbook"', text)
self.assertIn('install_mode = "subtree"', text)
self.assertIn("相对于 project_root", text)
self.assertIn("不是外部 clone 的 playbook 路径", text)
self.assertIn("snapshot 表示从外部 clone 安装快照", text)
self.assertNotIn("target_dir", text)
def test_deployment_docs_do_not_reference_legacy_terms(self):
self.assertNotIn("vendoring", README.read_text(encoding="utf-8"))
self.assertNotIn("`.tmp`", README.read_text(encoding="utf-8"))
self.assertNotIn("vendoring", SKILLS_DOC.read_text(encoding="utf-8"))
self.assertNotIn("vendoring", TEMPLATES_CI_README.read_text(encoding="utf-8"))
def test_repo_docs_use_platform_neutral_skills_source_dir(self):
readme_text = README.read_text(encoding="utf-8")
skills_text = SKILLS_DOC.read_text(encoding="utf-8")
templates_text = TEMPLATES_README.read_text(encoding="utf-8")
self.assertIn("`skills/`", readme_text)
self.assertIn("`skills/`", skills_text)
self.assertIn("├── skills/", templates_text)
self.assertNotIn("`codex/skills/`", readme_text)
self.assertNotIn("`codex/skills/`", skills_text)
self.assertNotIn("├── codex/skills/", templates_text)
def test_repo_no_longer_ships_tsl_guide_skill(self):
self.assertFalse(REMOVED_TSL_GUIDE.exists())
self.assertNotIn("tsl-guide", README.read_text(encoding="utf-8"))
self.assertNotIn("tsl-guide", SKILLS_DOC.read_text(encoding="utf-8"))
self.assertNotIn("$tsl-guide", RULESET_TSL.read_text(encoding="utf-8"))
def test_tsl_ruleset_describes_agent_first_file_model(self):
text = RULESET_TSL.read_text(encoding="utf-8")
self.assertIn("agent 判断流程", text)
self.assertIn("用户已给出 `.tsl` / `.tsf` 后缀时,后缀就是判断依据", text)
self.assertIn("`.tsl` 是可执行脚本", text)
self.assertIn("语句区按顺序执行", text)
self.assertIn("函数/类声明区", text)
self.assertIn("`.tsf` 是模块/函数扩展文件", text)
self.assertIn("funcext", text)
self.assertIn("仍不明确时向用户确认", text)
self.assertNotIn("`.tsl` 仅 `function`", text)
self.assertNotIn("脚本优先 `.tsl`,可复用扩展优先 `.tsf`", text)
def test_tsl_syntax_docs_keep_script_then_declarations_model(self):
quickstart = (ROOT / "docs/tsl/syntax/02_quickstart.md").read_text(
encoding="utf-8"
)
core_model = (ROOT / "docs/tsl/syntax/03_core_model.md").read_text(
encoding="utf-8"
)
functions = (ROOT / "docs/tsl/syntax/06_functions_and_calls.md").read_text(
encoding="utf-8"
)
pitfalls = (ROOT / "docs/tsl/syntax/12_pitfalls.md").read_text(
encoding="utf-8"
)
for text in (quickstart, core_model, functions, pitfalls):
self.assertIn("语句区", text)
self.assertIn("声明区", text)
self.assertIn("test();", quickstart)
self.assertIn("function test();", quickstart)
self.assertIn("脚本语句后可以接函数声明", functions)
self.assertIn("不要在声明区后面继续写脚本语句", pitfalls)
self.assertNotIn("不要把顶层函数定义和松散语句混写", quickstart)
self.assertNotIn("不要把顶层函数定义和松散语句混写", core_model)
self.assertNotIn("不要把顶层函数定义和松散语句混在同一个文件模型里", functions)
self.assertIn("后缀就是判断依据", quickstart)
self.assertIn("未给后缀", quickstart)
def test_tsl_agent_entrypoints_do_not_require_runtime_verification(self):
entrypoints = [
RULESET_TSL,
ROOT / "docs/tsl/index.md",
ROOT / "docs/tsl/syntax/index.md",
]
forbidden_phrases = [
"用当前解释器验证",
"本地用 `tsl` 验证",
"用 `tsl` 实测",
"最小实测",
"才写最小 `.tsl` / `.tsf` 例子",
]
for path in entrypoints:
text = path.read_text(encoding="utf-8")
for phrase in forbidden_phrases:
self.assertNotIn(phrase, text, msg=f"{phrase!r} found in {path}")
def test_tsl_index_requires_maintainer_verified_examples_before_publication(self):
text = (ROOT / "docs/tsl/index.md").read_text(encoding="utf-8")
self.assertIn("维护者入文档前验证", text)
self.assertIn("代码库样例", text)
self.assertIn("环境验证通过", text)
self.assertIn("不能写成语法事实", text)
self.assertIn("验证过程不写进语法页", text)
self.assertIn("agent 不需要自行执行验证", text)
def test_tsl_introduction_is_agent_first_decision_model(self):
text = TSL_INTRODUCTION.read_text(encoding="utf-8")
self.assertIn("agent", text)
self.assertIn("后缀就是判断依据", text)
self.assertIn("用户未给后缀", text)
self.assertIn("可执行代码对应 `.tsl`", text)
self.assertIn("通用模块对应 `.tsf`", text)
self.assertIn("`.tsl` 可执行脚本第一印象", text)
self.assertIn("`.tsf` 通用模块第一印象", text)
self.assertIn("不要发明语法", text)
self.assertIn("test();", text)
self.assertIn("function test();", text)
self.assertIn("function Test1();", text)
self.assertNotIn("先看顶层主体", text)
self.assertNotIn("顶层主体优先收敛成四类", text)
def test_tsl_quickstart_is_agent_coding_gate(self):
text = TSL_QUICKSTART.read_text(encoding="utf-8")
self.assertIn("Agent 快速落代码流程", text)
self.assertIn("先看用户有没有指定 `.tsl` / `.tsf` 后缀", text)
self.assertIn("再根据交付目标判断 `.tsl` 或 `.tsf`", text)
self.assertIn("只从 `代码块身份:已验证可执行示例` 的骨架起手", text)
self.assertIn("不要发明语法", text)
self.assertIn("不要在声明区后面继续追加脚本语句", text)
def test_tsl_quickstart_labels_observable_outputs(self):
text = TSL_QUICKSTART.read_text(encoding="utf-8")
self.assertIn("代码块身份:已验证输出片段", text)
self.assertIn("```text\ntest\n```", text)
self.assertIn("```text\n5\n```", text)
self.assertIn("```text\ntest1\n```", text)
self.assertIn("```text\nhello\n```", text)
def test_tsl_quickstart_omits_environment_verification_details(self):
text = TSL_QUICKSTART.read_text(encoding="utf-8")
for phrase in [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]:
self.assertNotIn(phrase, text)
def test_tsl_core_model_is_agent_file_model_decision_page(self):
text = TSL_CORE_MODEL.read_text(encoding="utf-8")
self.assertIn("Agent 文件模型判断流程", text)
self.assertIn("后缀是第一证据", text)
self.assertIn("可执行交付", text)
self.assertIn("可复用扩展交付", text)
self.assertIn("不要把 `.tsl` 写成只有顶层函数的模块", text)
self.assertIn("不要把 `.tsf` 写成会直接执行脚本语句的入口", text)
self.assertIn("没有文档证据时不要发明文件模型", text)
self.assertNotIn("误以为扩展名本身就完全决定能否写函数、类或 `unit`", text)
def test_tsl_core_model_examples_have_verified_outputs(self):
text = TSL_CORE_MODEL.read_text(encoding="utf-8")
self.assertIn("代码块身份:已验证输出片段", text)
self.assertIn("```text\ntest\n```", text)
self.assertIn("```text\n5\n```", text)
self.assertIn("```text\n1\n```", text)
self.assertIn("```text\ninvalid statement\n```", text)
def test_tsl_core_model_omits_environment_verification_details(self):
text = TSL_CORE_MODEL.read_text(encoding="utf-8")
for phrase in [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]:
self.assertNotIn(phrase, text)
def test_tsl_values_page_is_agent_value_decision_page(self):
text = TSL_VALUES.read_text(encoding="utf-8")
self.assertIn("Agent 值写法判断流程", text)
self.assertIn("普通值优先从整数、实数、普通字符串、布尔和 `array(...)` 起手", text)
self.assertIn("字符串默认用普通字符串", text)
self.assertIn("`L\"\"` / `U\"\"` 只在编码或宽串场景", text)
self.assertIn("先判断要顺序数组还是字符串键表", text)
self.assertIn("顺序数组和二进制缓冲区下标从 `0` 开始", text)
self.assertIn("字符串下标从 `1` 开始", text)
self.assertIn("没有已验证代码块时不要发明值写法", text)
def test_tsl_values_key_examples_have_verified_output_snippets(self):
text = TSL_VALUES.read_text(encoding="utf-8")
self.assertIn("代码块身份:已验证输出片段", text)
self.assertIn("```text\n1\n12.5\nABC\n1\n0\n2\n```", text)
self.assertIn("```text\n10\n20\n0001\nA\nB\nC\n```", text)
self.assertIn("```text\nBCD\n```", text)
self.assertIn("```text\nString index out of bounds\n```", text)
def test_tsl_values_omits_environment_verification_details(self):
text = TSL_VALUES.read_text(encoding="utf-8")
for phrase in [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]:
self.assertNotIn(phrase, text)
def test_tsl_variables_page_is_agent_binding_decision_page(self):
text = TSL_VARIABLES.read_text(encoding="utf-8")
self.assertIn("Agent 变量/常量判断流程", text)
self.assertIn("普通变量默认直接用 `:=` 首次赋值", text)
self.assertIn("只有用户要求显式声明或遇到 `{$Explicit+}` 时才优先写 `var`", text)
self.assertIn("顶层脚本常量优先用 `const name := value;`", text)
self.assertIn("`const Name = value;` 优先放在函数 `const` 段、`unit` 接口或类成员里", text)
self.assertIn("单变量拆包必须写成 `[name, ] := array(...)`", text)
self.assertIn("没有已验证代码块时不要发明变量/常量写法", text)
def test_tsl_variables_key_examples_have_verified_output_snippets(self):
text = TSL_VARIABLES.read_text(encoding="utf-8")
self.assertIn("代码块身份:已验证输出片段", text)
self.assertIn("```text\n1\n2\n```", text)
self.assertIn("```text\n7\n```", text)
self.assertIn("```text\n1\n3\n```", text)
self.assertIn("```text\n1\n1\n```", text)
self.assertIn("```text\nvariable not defined\n```", text)
def test_tsl_variables_omits_environment_verification_details(self):
text = TSL_VARIABLES.read_text(encoding="utf-8")
for phrase in [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]:
self.assertNotIn(phrase, text)
def test_tsl_functions_page_is_agent_function_decision_page(self):
text = TSL_FUNCTIONS.read_text(encoding="utf-8")
self.assertIn("Agent 函数/调用判断流程", text)
self.assertIn("先判断当前文件是 `.tsl` 还是 `.tsf`", text)
self.assertIn("`.tsl` 中先写语句区,再把 `function` / `procedure` 声明放在后面", text)
self.assertIn("需要返回值时用 `function`,不需要返回值时用 `procedure`", text)
self.assertIn("命名参数只写 `name: value`", text)
self.assertIn("不要把 `name = value` 当成命名参数", text)
self.assertIn("没有已验证代码块时不要发明函数/调用写法", text)
self.assertNotIn("在我于", text)
def test_tsl_functions_key_examples_have_verified_output_snippets(self):
text = TSL_FUNCTIONS.read_text(encoding="utf-8")
self.assertIn("代码块身份:已验证输出片段", text)
self.assertIn("```text\ntest\n```", text)
self.assertIn("```text\n2\n```", text)
self.assertIn("```text\n12\n```", text)
self.assertIn("```text\ninvalid statement\n```", text)
def test_tsl_functions_omits_environment_verification_details(self):
text = TSL_FUNCTIONS.read_text(encoding="utf-8")
for phrase in [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]:
self.assertNotIn(phrase, text)
def test_tsl_expressions_page_is_agent_expression_decision_page(self):
text = TSL_EXPRESSIONS.read_text(encoding="utf-8")
self.assertIn("Agent 表达式/运算符判断流程", text)
self.assertIn("先判断要写赋值、比较、条件求值、表达式对象、空安全访问还是链式比较", text)
self.assertIn("赋值只能用 `:=`", text)
self.assertIn("比较才用 `=`", text)
self.assertIn("条件求值优先用 `flag ? true_value : false_value`", text)
self.assertIn("`if condition then true_value else false_value` 必须带 `else`", text)
self.assertIn("没有已验证代码块时不要发明表达式/运算符写法", text)
self.assertNotIn("当前环境里", text)
def test_tsl_expressions_key_examples_have_verified_output_snippets(self):
text = TSL_EXPRESSIONS.read_text(encoding="utf-8")
self.assertIn("代码块身份:已验证输出片段", text)
self.assertIn("```text\n3\n```", text)
self.assertIn("```text\nAB\n```", text)
self.assertIn("```text\n222888\n1\n1\n1\n1\n```", text)
self.assertIn("```text\n1\n0\n```", text)
self.assertIn("```text\n2\n```", text)
self.assertIn("```text\n6\n```", text)
self.assertIn("```text\n1\n7\n1\n```", text)
self.assertIn("```text\ninvalid statement\n```", text)
def test_tsl_expressions_omits_environment_verification_details(self):
text = TSL_EXPRESSIONS.read_text(encoding="utf-8")
for phrase in [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]:
self.assertNotIn(phrase, text)
def test_remaining_tsl_syntax_pages_are_agent_decision_pages(self):
syntax_root = ROOT / "docs" / "tsl" / "syntax"
for filename, section in TSL_REMAINING_SYNTAX_AGENT_SECTIONS.items():
with self.subTest(filename=filename):
text = (syntax_root / filename).read_text(encoding="utf-8")
self.assertIn(section, text)
self.assertIn("agent", text.lower())
self.assertIn("不要发明", text)
def test_remaining_tsl_syntax_pages_have_verified_output_snippets(self):
syntax_root = ROOT / "docs" / "tsl" / "syntax"
for filename in TSL_REMAINING_SYNTAX_AGENT_SECTIONS:
with self.subTest(filename=filename):
text = (syntax_root / filename).read_text(encoding="utf-8")
if (
"代码块身份:已验证可执行示例" in text
or "代码块身份:反例 / 不可照写" in text
):
self.assertIn("代码块身份:已验证输出片段", text)
def test_remaining_tsl_syntax_pages_omit_personal_and_environment_details(self):
syntax_root = ROOT / "docs" / "tsl" / "syntax"
forbidden_phrases = [
"我在",
"当前环境里",
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
]
for filename in TSL_REMAINING_SYNTAX_AGENT_SECTIONS:
with self.subTest(filename=filename):
text = (syntax_root / filename).read_text(encoding="utf-8")
for phrase in forbidden_phrases:
self.assertNotIn(phrase, text)
def test_tsl_reference_index_requires_verified_function_workflow(self):
text = TSL_REFERENCE_INDEX.read_text(encoding="utf-8")
self.assertIn("Agent 函数使用规则", text)
self.assertIn("只从 verified 函数页读取参数类型", text)
self.assertIn("catalog 只是候选函数索引", text)
self.assertIn("确认每个方法的参数类型", text)
self.assertIn("verified/index.md", text)
self.assertIn("verified/core.md", text)
self.assertIn("unavailable_methods.md", text)
self.assertIn("不能把 catalog 里的函数名直接当成可调用事实", text)
self.assertNotIn("verification_failures", text)
self.assertNotIn("函数入库验证流程", text)
self.assertNotIn("验证过程", text)
self.assertNotIn("代码块身份", text)
self.assertNotIn("已验证输出片段", text)
self.assertNotIn("验证失败", text)
def test_tsl_reference_catalog_is_candidate_index_not_callable_fact(self):
catalog_index = TSL_REFERENCE_CATALOG_INDEX.read_text(encoding="utf-8")
self.assertIn("候选函数索引", catalog_index)
self.assertIn("候选名没有进入 verified 函数页前不能当成可调用事实", catalog_index)
self.assertIn("../verified/index.md", catalog_index)
self.assertIn("../verified/core.md", catalog_index)
self.assertIn("只从 verified 函数页读取参数类型", catalog_index)
self.assertNotIn("错误参数组合", catalog_index)
self.assertNotIn("参数验证", catalog_index)
for path in (ROOT / "docs" / "tsl" / "reference" / "catalog").glob("*.md"):
text = path.read_text(encoding="utf-8")
self.assertIn("候选函数索引", text, msg=f"{path.name} missing candidate warning")
self.assertIn("只从 verified 函数页读取参数类型", text)
def test_tsl_reference_verified_index_routes_to_parameter_fact_pages(self):
text = TSL_REFERENCE_VERIFIED_INDEX.read_text(encoding="utf-8")
self.assertIn("文档类型agent 参数事实索引", text)
self.assertIn("core.md", text)
self.assertIn("Abs", text)
self.assertIn("ifInt", text)
self.assertIn("DateToStr", text)
self.assertIn("Length", text)
self.assertIn("只从具体函数页读取接收类型", text)
self.assertNotIn("验证过程", text)
self.assertNotIn("代码块身份", text)
def test_tsl_reference_verified_core_records_agent_parameter_facts(self):
text = TSL_REFERENCE_VERIFIED_CORE.read_text(encoding="utf-8")
self.assertIn("文档类型agent 参数事实表", text)
self.assertIn("接收类型", text)
self.assertIn("返回", text)
self.assertIn("`Abs(value)`", text)
self.assertIn("`ifInt(value)`", text)
self.assertIn("`DateToStr(value)`", text)
self.assertIn("`Length(value)`", text)
self.assertIn("整数", text)
self.assertIn("实数", text)
self.assertIn("字符串", text)
self.assertIn("数组", text)
self.assertIn("日期时间", text)
self.assertNotIn("代码块身份", text)
self.assertNotIn("已验证输出片段", text)
self.assertNotIn("Function Abs execution error", text)
self.assertNotIn("错误参数", text)
def test_tsl_reference_all_markdown_avoid_verification_logs(self):
for path in (ROOT / "docs" / "tsl" / "reference").rglob("*.md"):
text = path.read_text(encoding="utf-8")
with self.subTest(path=path.relative_to(ROOT)):
self.assertNotIn("验证过程", text)
self.assertNotIn("函数入库验证流程", text)
self.assertNotIn("代码块身份", text)
self.assertNotIn("已验证输出片段", text)
self.assertNotIn("Function Abs execution error", text)
def test_tsl_reference_unavailable_records_only_unavailable_methods(self):
text = TSL_REFERENCE_UNAVAILABLE.read_text(encoding="utf-8")
self.assertIn("文档类型:当前测试环境不支持的方法清单", text)
self.assertIn("当前测试环境不支持的方法", text)
self.assertIn("暂无已入档记录", text)
self.assertNotIn("failure", text.lower())
self.assertNotIn("失败", text)
self.assertNotIn("验证过程", text)
self.assertNotIn("参数类型错误", text)
self.assertNotIn("`Abs(\"-3\")`", text)
self.assertNotIn("`Abs()`", text)
self.assertNotIn("`DateToStr(\"2011-12-31\")`", text)
self.assertNotIn("`DateToStr()`", text)
self.assertNotIn("`Length(123)`", text)
self.assertNotIn("Function Abs execution error", text)
def test_tsl_reference_docs_do_not_name_valid_parameter_mismatches_as_failures(self):
reference_root = ROOT / "docs" / "tsl" / "reference"
for path in reference_root.rglob("*.md"):
text = path.read_text(encoding="utf-8")
with self.subTest(path=path.relative_to(ROOT)):
self.assertNotIn("verification_failures", text)
self.assertNotIn("错误参数", text)
self.assertNotIn("验证失败", text)
self.assertNotIn("Abs(\"-3\")", text)
self.assertNotIn("DateToStr(\"2011-12-31\")", text)
self.assertNotIn("Length(123)", text)
def test_tsl_finance_docs_are_agent_business_decision_pages(self):
finance_root = ROOT / "docs" / "tsl" / "finance"
for path in finance_root.glob("*.md"):
text = path.read_text(encoding="utf-8")
with self.subTest(path=path.name):
self.assertIn("Agent", text)
self.assertIn("不要发明", text)
self.assertIn("项目实际接口", text)
self.assertNotIn("是否含已验证", text)
self.assertNotIn("代码块身份", text)
self.assertNotIn("验证过程", text)
def test_tsl_finance_index_routes_all_finance_pages(self):
text = TSL_FINANCE_INDEX.read_text(encoding="utf-8")
self.assertIn("Agent Finance 路由规则", text)
self.assertIn("entry_decision.md", text)
self.assertIn("market_data_context.md", text)
self.assertIn("series_and_indicator_model.md", text)
self.assertIn("selection_and_signal_patterns.md", text)
self.assertIn("backtest_and_trade_flow.md", text)
def test_tsl_modules_docs_are_agent_integration_boundary_pages(self):
modules_root = ROOT / "docs" / "tsl" / "modules"
for path in modules_root.glob("*.md"):
text = path.read_text(encoding="utf-8")
with self.subTest(path=path.name):
self.assertIn("Agent", text)
self.assertIn("不要发明", text)
self.assertNotIn("是否含已验证", text)
self.assertNotIn("代码块身份", text)
self.assertNotIn("验证过程", text)
def test_tsl_modules_index_routes_all_module_pages(self):
text = TSL_MODULES_INDEX.read_text(encoding="utf-8")
self.assertIn("Agent Modules 路由规则", text)
self.assertIn("tsbacktesting.md", text)
self.assertIn("tsl_python_interop.md", text)
self.assertIn("wechat_message.md", text)
self.assertIn("pytsl_api.md", text)
def test_tsl_finance_and_modules_omit_environment_verification_details(self):
forbidden_phrases = [
"Docker",
"docker exec",
"LD_LIBRARY_PATH",
"/data/workspace",
"U22Cli",
"gitea-runner",
"当前环境里",
"实测",
]
for root_name in ("finance", "modules"):
for path in (ROOT / "docs" / "tsl" / root_name).glob("*.md"):
text = path.read_text(encoding="utf-8")
for phrase in forbidden_phrases:
self.assertNotIn(phrase, text, msg=f"{phrase!r} found in {path}")
if __name__ == "__main__":
unittest.main()