🔧 chore(playbook): split sync_templates into sections

This commit is contained in:
csh
2026-01-27 08:49:40 +08:00
parent 278750e3c9
commit 73d5c261b1
7 changed files with 263 additions and 113 deletions
+184 -75
View File
@@ -10,7 +10,15 @@ try:
except ModuleNotFoundError: # Python < 3.11
tomllib = None
ORDER = ["vendor", "sync_templates", "sync_standards", "install_skills", "format_md"]
ORDER = [
"vendor",
"sync_rules",
"sync_memory_bank",
"sync_prompts",
"sync_standards",
"install_skills",
"format_md",
]
SCRIPT_DIR = Path(__file__).resolve().parent
PLAYBOOK_ROOT = SCRIPT_DIR.parent
@@ -503,15 +511,125 @@ def update_agents_section(
log("Appended: AGENTS.md (section)")
def sync_templates_action(config: dict, context: dict) -> int:
def resolve_project_name(context: dict) -> str | None:
config = context.get("config", {})
if not isinstance(config, dict):
return None
memory_conf = config.get("sync_memory_bank")
if isinstance(memory_conf, dict):
raw = memory_conf.get("project_name")
if raw is not None and str(raw).strip():
return str(raw).strip()
return None
def resolve_template_date(context: dict) -> str:
config = context.get("config", {})
if isinstance(config, dict):
for key in ("sync_rules", "sync_memory_bank", "sync_prompts"):
section = config.get(key)
if isinstance(section, dict):
value = section.get("date")
if value:
return str(value)
return datetime.now().strftime("%Y-%m-%d")
def sync_agents_template(context: dict) -> int:
project_root: Path = context["project_root"]
if project_root.resolve() == PLAYBOOK_ROOT.resolve():
log("Skip: playbook root equals project root.")
return 0
templates_dir = PLAYBOOK_ROOT / "templates"
if not templates_dir.is_dir():
print(f"ERROR: templates not found: {templates_dir}", file=sys.stderr)
agents_src = templates_dir / "AGENTS.template.md"
if not agents_src.is_file():
return 0
project_name = resolve_project_name(context)
main_language = resolve_main_language({}, context)
playbook_scripts = resolve_playbook_scripts(project_root, context)
date_value = resolve_template_date(context)
agents_dst = project_root / "AGENTS.md"
if agents_dst.exists():
agents_text = agents_dst.read_text(encoding="utf-8")
if "<!-- playbook:framework:start -->" in agents_text:
start_marker = "<!-- playbook:framework:start -->"
end_marker = "<!-- playbook:framework:end -->"
elif "<!-- playbook:templates:start -->" in agents_text:
start_marker = "<!-- playbook:templates:start -->"
end_marker = "<!-- playbook:templates:end -->"
else:
start_marker = "<!-- playbook:templates:start -->"
end_marker = "<!-- playbook:templates:end -->"
else:
start_marker = "<!-- playbook:framework:start -->"
end_marker = "<!-- playbook:framework:end -->"
update_agents_section(
agents_dst,
agents_src,
start_marker,
end_marker,
project_name,
date_value,
main_language,
playbook_scripts,
)
return 0
def should_sync_agents(config: dict) -> bool:
for key in ("sync_rules", "sync_memory_bank", "sync_prompts", "sync_standards"):
if key in config:
return True
return False
def sync_rules_action(config: dict, context: dict) -> int:
project_root: Path = context["project_root"]
if project_root.resolve() == PLAYBOOK_ROOT.resolve():
log("Skip: playbook root equals project root.")
return 0
templates_dir = PLAYBOOK_ROOT / "templates"
rules_src = templates_dir / "AGENT_RULES.template.md"
if not rules_src.is_file():
print(f"ERROR: template not found: {rules_src}", file=sys.stderr)
return 2
rules_dst = project_root / "AGENT_RULES.md"
force = bool(config.get("force", False))
if rules_dst.exists() and not force:
log("AGENT_RULES.md already exists. Use force to overwrite.")
return 0
project_name = resolve_project_name(context)
main_language = resolve_main_language(config, context)
playbook_scripts = resolve_playbook_scripts(project_root, context)
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
backup_path(rules_dst, False)
text = rules_src.read_text(encoding="utf-8")
text = replace_placeholders(
text, project_name, date_value, main_language, playbook_scripts
)
rules_dst.write_text(text + "\n", encoding="utf-8")
log("Synced: AGENT_RULES.md")
return 0
def sync_memory_bank_action(config: dict, context: dict) -> int:
project_root: Path = context["project_root"]
if project_root.resolve() == PLAYBOOK_ROOT.resolve():
log("Skip: playbook root equals project root.")
return 0
templates_dir = PLAYBOOK_ROOT / "templates"
memory_src = templates_dir / "memory-bank"
if not memory_src.is_dir():
print(f"ERROR: templates not found: {memory_src}", file=sys.stderr)
return 2
project_name = config.get("project_name")
@@ -520,80 +638,62 @@ def sync_templates_action(config: dict, context: dict) -> int:
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
force = bool(config.get("force", False))
no_backup = bool(config.get("no_backup", False))
full = bool(config.get("full", False))
memory_src = templates_dir / "memory-bank"
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(
memory_dst,
project_name,
date_value,
main_language,
playbook_scripts,
)
log("Synced: memory-bank/")
return 0
def sync_prompts_action(config: dict, context: dict) -> int:
project_root: Path = context["project_root"]
if project_root.resolve() == PLAYBOOK_ROOT.resolve():
log("Skip: playbook root equals project root.")
return 0
templates_dir = PLAYBOOK_ROOT / "templates"
prompts_src = templates_dir / "prompts"
agents_src = templates_dir / "AGENTS.template.md"
rules_src = templates_dir / "AGENT_RULES.template.md"
if not prompts_src.is_dir():
print(f"ERROR: templates not found: {prompts_src}", file=sys.stderr)
return 2
if memory_src.is_dir():
memory_dst = project_root / "memory-bank"
if memory_dst.exists() and not force:
log("memory-bank/ already exists. Use force to overwrite.")
else:
backup_path(memory_dst, no_backup)
copytree(memory_src, memory_dst)
rename_template_files(memory_dst)
replace_placeholders_in_dir(
memory_dst,
project_name,
date_value,
main_language,
playbook_scripts,
)
log("Synced: memory-bank/")
project_name = resolve_project_name(context)
main_language = resolve_main_language(config, context)
playbook_scripts = resolve_playbook_scripts(project_root, context)
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
force = bool(config.get("force", False))
no_backup = bool(config.get("no_backup", False))
if prompts_src.is_dir():
prompts_dst = project_root / "docs/prompts"
if prompts_dst.exists() and not force:
log("docs/prompts/ already exists. Use force to overwrite.")
else:
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(
prompts_dst,
project_name,
date_value,
main_language,
playbook_scripts,
)
log("Synced: docs/prompts/")
if agents_src.is_file():
agents_dst = project_root / "AGENTS.md"
if full:
start_marker = "<!-- playbook:framework:start -->"
end_marker = "<!-- playbook:framework:end -->"
else:
start_marker = "<!-- playbook:templates:start -->"
end_marker = "<!-- playbook:templates:end -->"
update_agents_section(
agents_dst,
agents_src,
start_marker,
end_marker,
project_name,
date_value,
main_language,
playbook_scripts,
)
if rules_src.is_file():
rules_dst = project_root / "AGENT_RULES.md"
if rules_dst.exists() and not force:
log("AGENT_RULES.md already exists. Use force to overwrite.")
else:
backup_path(rules_dst, no_backup)
text = rules_src.read_text(encoding="utf-8")
text = replace_placeholders(
text, project_name, date_value, main_language, playbook_scripts
)
rules_dst.write_text(text + "\n", encoding="utf-8")
log("Synced: AGENT_RULES.md")
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(
prompts_dst,
project_name,
date_value,
main_language,
playbook_scripts,
)
log("Synced: docs/prompts/")
return 0
@@ -959,8 +1059,12 @@ def run_action(name: str, config: dict, context: dict) -> int:
print(f"[action] {name}")
if name == "vendor":
return vendor_action(config, context)
if name == "sync_templates":
return sync_templates_action(config, context)
if name == "sync_rules":
return sync_rules_action(config, context)
if name == "sync_memory_bank":
return sync_memory_bank_action(config, context)
if name == "sync_prompts":
return sync_prompts_action(config, context)
if name == "sync_standards":
return sync_standards_action(config, context)
if name == "install_skills":
@@ -1002,6 +1106,11 @@ def main(argv: list[str]) -> int:
"config": config,
}
if should_sync_agents(config):
result = sync_agents_template(context)
if result != 0:
return result
for name in ORDER:
if name in config:
result = run_action(name, config[name], context)