From 60ff3cd035a22689af2830bc12f5992fb16bc71e Mon Sep 17 00:00:00 2001 From: csh Date: Tue, 27 Jan 2026 16:54:18 +0800 Subject: [PATCH] :bug: fix(playbook): sync templates per file --- scripts/playbook.py | 104 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/scripts/playbook.py b/scripts/playbook.py index 7eda6f1..ef3656f 100644 --- a/scripts/playbook.py +++ b/scripts/playbook.py @@ -364,9 +364,26 @@ def vendor_action(config: dict, context: dict) -> int: if (rulesets_root / "index.md").is_file(): copy2(rulesets_root / "index.md", dest_prefix / "rulesets/index.md") - templates_ci = PLAYBOOK_ROOT / "templates/ci" + templates_root = PLAYBOOK_ROOT / "templates" + templates_dst = dest_prefix / "templates" + ensure_dir(templates_dst) + + templates_ci = templates_root / "ci" if templates_ci.is_dir(): - copytree(templates_ci, dest_prefix / "templates/ci") + copytree(templates_ci, templates_dst / "ci") + + for name in ("AGENTS.template.md", "AGENT_RULES.template.md", "README.md"): + src = templates_root / name + if src.is_file(): + copy2(src, templates_dst / name) + + memory_src = templates_root / "memory-bank" + if memory_src.is_dir(): + copytree(memory_src, templates_dst / "memory-bank") + + prompts_src = templates_root / "prompts" + if prompts_src.is_dir(): + copytree(prompts_src, templates_dst / "prompts") for lang in langs: docs_src = PLAYBOOK_ROOT / "docs" / lang @@ -443,6 +460,63 @@ def replace_placeholders_in_dir( file_path.write_text(updated, encoding="utf-8") +def replace_placeholders_in_file( + file_path: Path, + project_name: str | None, + date_value: str, + main_language: str | None, + playbook_scripts: str | None, +) -> None: + if file_path.suffix != ".md": + return + text = file_path.read_text(encoding="utf-8") + updated = replace_placeholders( + text, project_name, date_value, main_language, playbook_scripts + ) + if updated != text: + file_path.write_text(updated, encoding="utf-8") + + +def resolve_template_target( + template_file: Path, template_root: Path, target_root: Path +) -> Path: + rel = template_file.relative_to(template_root) + if rel.name.endswith(".template.md"): + rel = rel.with_name(rel.name.replace(".template.md", ".md")) + return target_root / rel + + +def sync_directory( + template_dir: Path, + target_dir: Path, + project_name: str | None, + date_value: str, + main_language: str | None, + playbook_scripts: str | None, + force: bool, + no_backup: bool, +) -> None: + for template_file in template_dir.rglob("*"): + if not template_file.is_file(): + continue + target_file = resolve_template_target( + template_file, template_dir, target_dir + ) + ensure_dir(target_file.parent) + if target_file.exists(): + if not force: + continue + backup_path(target_file, no_backup) + copy2(template_file, target_file) + replace_placeholders_in_file( + target_file, + project_name, + date_value, + main_language, + playbook_scripts, + ) + + def extract_block_lines(text: str, start: str, end: str) -> list[str]: lines = text.splitlines() block: list[str] = [] @@ -640,19 +714,16 @@ def sync_memory_bank_action(config: dict, context: dict) -> int: no_backup = bool(config.get("no_backup", False)) memory_dst = project_root / "memory-bank" - if memory_dst.exists() and not force: - log("memory-bank/ already exists. Use force to overwrite.") - return 0 - - backup_path(memory_dst, no_backup) - copytree(memory_src, memory_dst) - rename_template_files(memory_dst) - replace_placeholders_in_dir( + ensure_dir(memory_dst) + sync_directory( + memory_src, memory_dst, project_name, date_value, main_language, playbook_scripts, + force, + no_backup, ) log("Synced: memory-bank/") return 0 @@ -678,20 +749,17 @@ def sync_prompts_action(config: dict, context: dict) -> int: no_backup = bool(config.get("no_backup", False)) prompts_dst = project_root / "docs/prompts" - if prompts_dst.exists() and not force: - log("docs/prompts/ already exists. Use force to overwrite.") - return 0 - - backup_path(prompts_dst, no_backup) ensure_dir(prompts_dst.parent) - copytree(prompts_src, prompts_dst) - rename_template_files(prompts_dst) - replace_placeholders_in_dir( + ensure_dir(prompts_dst) + sync_directory( + prompts_src, prompts_dst, project_name, date_value, main_language, playbook_scripts, + force, + no_backup, ) log("Synced: docs/prompts/") return 0