feat(playbook): add no_backup deploy controls

remove obsolete main_language placeholders and language summary template text

limit generated .agents guidance to configured langs and normalize AGENT_RULES trailing newlines

document install_skills no_backup behavior and refresh tests for deployment links and sync flows
This commit is contained in:
csh
2026-04-24 10:06:03 +08:00
parent 8609d59d4a
commit a2e3cb07de
12 changed files with 138 additions and 90 deletions
+23
View File
@@ -237,6 +237,29 @@ no_backup = true
self.assertIn("`.agents/tsl/index.md`", agents_index)
self.assertIn("`.agents/cpp/index.md`", agents_index)
def test_sync_standards_agents_index_only_lists_configured_langs(self):
with tempfile.TemporaryDirectory() as tmp_dir:
root = Path(tmp_dir)
config_body = f"""
[playbook]
project_root = "{tmp_dir}"
deploy_root = "{CUSTOM_DEPLOY_ROOT}"
[sync_standards]
langs = ["tsl", "markdown"]
"""
config_path = write_config(root, "playbook.toml", config_body)
result = run_cli("-config", str(config_path))
self.assertEqual(result.returncode, 0, msg=result.stdout + result.stderr)
agents_index = (root / ".agents" / "index.md").read_text(encoding="utf-8")
self.assertIn("`.agents/tsl/`TSL 相关规则集", agents_index)
self.assertIn("`.agents/markdown/`Markdown 相关规则集", agents_index)
self.assertNotIn("`.agents/cpp/`", agents_index)
self.assertNotIn("`.agents/python/`", agents_index)
self.assertNotIn("`.agents/typescript/`", agents_index)
def test_sync_standards_agents_block_has_blank_lines(self):
with tempfile.TemporaryDirectory() as tmp_dir:
config_body = f"""
+30
View File
@@ -74,6 +74,36 @@ no_backup = true
git_backups = list(root.glob(".gitattributes.bak.*"))
self.assertEqual(git_backups, [])
def test_install_skills_no_backup_replaces_existing_skill_without_backup(self):
with tempfile.TemporaryDirectory() as tmp_dir:
root = Path(tmp_dir)
skills_root = root / "agents" / "skills"
existing = skills_root / "brainstorming"
existing.mkdir(parents=True)
(existing / "stale.txt").write_text("old", encoding="utf-8")
config_body = f"""
[playbook]
project_root = "{tmp_dir}"
deploy_root = "{DEFAULT_DEPLOY_ROOT}"
[install_skills]
agents_home = "{root / 'agents'}"
mode = "list"
skills = ["brainstorming"]
no_backup = true
"""
config_path = root / "playbook.toml"
config_path.write_text(config_body, encoding="utf-8")
result = run_cli("-config", str(config_path))
self.assertEqual(result.returncode, 0, msg=result.stderr)
backups = list(skills_root.glob("brainstorming.bak.*"))
self.assertEqual(backups, [])
self.assertFalse((existing / "stale.txt").exists())
self.assertTrue((existing / "SKILL.md").is_file())
if __name__ == "__main__":
unittest.main()
+32 -1
View File
@@ -27,7 +27,29 @@ def run_script(script_path: Path, *args, cwd: Path | None = None):
class SyncTemplatesPlaceholdersTests(unittest.TestCase):
def test_main_language_placeholder_replaced(self):
def test_templates_no_longer_expose_main_language_placeholder(self):
example_text = (ROOT / "playbook.toml.example").read_text(encoding="utf-8")
self.assertNotIn("main_language", example_text)
templates_readme = (ROOT / "templates" / "README.md").read_text(
encoding="utf-8"
)
self.assertNotIn("{{MAIN_LANGUAGE}}", templates_readme)
self.assertNotIn("{{LANGUAGE_1}}", templates_readme)
agents_template = (ROOT / "templates" / "AGENTS.template.md").read_text(
encoding="utf-8"
)
self.assertNotIn("{{MAIN_LANGUAGE}}", agents_template)
tech_stack_template = (
ROOT / "templates" / "memory-bank" / "tech-stack.template.md"
).read_text(encoding="utf-8")
self.assertNotIn("{{MAIN_LANGUAGE}}", tech_stack_template)
self.assertNotIn("{{LANGUAGE_1}}", tech_stack_template)
self.assertNotIn("**主要语言**", tech_stack_template)
def test_sync_templates_replaces_playbook_scripts_without_main_language_support(self):
with tempfile.TemporaryDirectory() as tmp_dir:
config_body = f"""
[playbook]
@@ -36,6 +58,8 @@ deploy_root = "{DEFAULT_DEPLOY_ROOT}"
[sync_rules]
[sync_memory_bank]
[sync_standards]
langs = [\"cpp\", \"tsl\"]
"""
@@ -50,6 +74,12 @@ langs = [\"cpp\", \"tsl\"]
self.assertIn(".agents/cpp/index.md", text)
self.assertNotIn("{{MAIN_LANGUAGE}}", text)
tech_stack = Path(tmp_dir) / "memory-bank" / "tech-stack.md"
tech_stack_text = tech_stack.read_text(encoding="utf-8")
self.assertNotIn("{{LANGUAGE_1}}", tech_stack_text)
self.assertNotIn("{{MAIN_LANGUAGE}}", tech_stack_text)
self.assertNotIn("**主要语言**", tech_stack_text)
rules_md = Path(tmp_dir) / "AGENT_RULES.md"
rules_text = rules_md.read_text(encoding="utf-8")
self.assertIn("docs/standards/playbook/scripts/main_loop.py claim", rules_text)
@@ -57,6 +87,7 @@ langs = [\"cpp\", \"tsl\"]
self.assertIn("不得直接使用 `$executing-plans`", rules_text)
self.assertIn("不得直接使用 `$subagent-driven-development`", rules_text)
self.assertNotIn("{{PLAYBOOK_SCRIPTS}}", rules_text)
self.assertFalse(rules_text.endswith("\n\n"))
def test_sync_standards_rewrites_typescript_docs_prefix_for_vendored_playbook(self):
with tempfile.TemporaryDirectory() as tmp_dir:
@@ -8,6 +8,7 @@ PLAYBOOK_EXAMPLE = ROOT / "playbook.toml.example"
SKILLS_DOC = ROOT / "SKILLS.md"
TEMPLATES_CI_README = ROOT / "templates" / "ci" / "README.md"
REMOVED_TSL_GUIDE = ROOT / "codex" / "skills" / "tsl-guide"
REFERENCE_CATALOG_SOURCE_INDEX = ROOT / "data" / "tsl_reference_catalog_source" / "index.md"
class TslEntrypointsConsistencyTests(unittest.TestCase):
@@ -51,6 +52,11 @@ class TslEntrypointsConsistencyTests(unittest.TestCase):
self.assertNotIn("tsl-guide", SKILLS_DOC.read_text(encoding="utf-8"))
self.assertNotIn("$tsl-guide", RULESET_TSL.read_text(encoding="utf-8"))
def test_reference_catalog_source_index_uses_canonical_reference_entrypoint(self):
text = REFERENCE_CATALOG_SOURCE_INDEX.read_text(encoding="utf-8")
self.assertIn("docs/tsl/reference/catalog/index.md", text)
self.assertNotIn("docs/tsl/syntax_book/function/index.md", text)
if __name__ == "__main__":
unittest.main()