feat(playbook): add plan progress tracking and rules updates

This commit is contained in:
csh
2026-01-26 16:51:23 +08:00
parent 6efd637119
commit 278750e3c9
23 changed files with 919 additions and 275 deletions
+97 -9
View File
@@ -168,6 +168,45 @@ def normalize_langs(raw: object) -> list[str]:
return cleaned
def resolve_main_language(config: dict, context: dict) -> str:
raw = config.get("main_language")
if raw is not None and str(raw).strip():
return str(raw).strip()
full_config = context.get("config", {})
if isinstance(full_config, dict):
sync_conf = full_config.get("sync_standards")
if isinstance(sync_conf, dict):
langs_raw = sync_conf.get("langs")
if langs_raw is not None:
try:
langs = normalize_langs(langs_raw)
except ValueError:
langs = []
if langs:
return langs[0]
return "tsl"
def resolve_playbook_scripts(project_root: Path, context: dict) -> str:
playbook_scripts = PLAYBOOK_ROOT / "scripts"
try:
rel = playbook_scripts.resolve().relative_to(project_root.resolve())
return rel.as_posix()
except ValueError:
full_config = context.get("config", {})
if isinstance(full_config, dict):
vendor_conf = full_config.get("vendor")
if isinstance(vendor_conf, dict):
target_dir = vendor_conf.get("target_dir")
if target_dir:
target_str = str(target_dir).strip().rstrip("/").rstrip("\\")
if target_str:
return f"{target_str}/scripts"
return "docs/standards/playbook/scripts"
def read_git_commit(root: Path) -> str:
try:
result = subprocess.run(
@@ -348,10 +387,20 @@ def vendor_action(config: dict, context: dict) -> int:
return 0
def replace_placeholders(text: str, project_name: str | None, date_value: str) -> str:
def replace_placeholders(
text: str,
project_name: str | None,
date_value: str,
main_language: str | None,
playbook_scripts: str | None,
) -> str:
result = text.replace("{{DATE}}", date_value)
if project_name:
result = result.replace("{{PROJECT_NAME}}", project_name)
if main_language:
result = result.replace("{{MAIN_LANGUAGE}}", main_language)
if playbook_scripts:
result = result.replace("{{PLAYBOOK_SCRIPTS}}", playbook_scripts)
return result
@@ -370,10 +419,18 @@ def rename_template_files(root: Path) -> None:
template.rename(target)
def replace_placeholders_in_dir(root: Path, project_name: str | None, date_value: str) -> None:
def replace_placeholders_in_dir(
root: Path,
project_name: str | None,
date_value: str,
main_language: str | None,
playbook_scripts: str | None,
) -> None:
for file_path in root.rglob("*.md"):
text = file_path.read_text(encoding="utf-8")
updated = replace_placeholders(text, project_name, date_value)
updated = replace_placeholders(
text, project_name, date_value, main_language, playbook_scripts
)
if updated != text:
file_path.write_text(updated, encoding="utf-8")
@@ -401,9 +458,13 @@ def update_agents_section(
end_marker: str,
project_name: str | None,
date_value: str,
main_language: str | None,
playbook_scripts: str | None,
) -> None:
template_text = template_path.read_text(encoding="utf-8")
template_text = replace_placeholders(template_text, project_name, date_value)
template_text = replace_placeholders(
template_text, project_name, date_value, main_language, playbook_scripts
)
block = extract_block_lines(template_text, start_marker, end_marker)
if not block:
log("Skip: markers not found in template")
@@ -454,6 +515,8 @@ def sync_templates_action(config: dict, context: dict) -> int:
return 2
project_name = config.get("project_name")
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))
@@ -472,7 +535,13 @@ def sync_templates_action(config: dict, context: dict) -> int:
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)
replace_placeholders_in_dir(
memory_dst,
project_name,
date_value,
main_language,
playbook_scripts,
)
log("Synced: memory-bank/")
if prompts_src.is_dir():
@@ -484,7 +553,13 @@ def sync_templates_action(config: dict, context: dict) -> int:
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)
replace_placeholders_in_dir(
prompts_dst,
project_name,
date_value,
main_language,
playbook_scripts,
)
log("Synced: docs/prompts/")
if agents_src.is_file():
@@ -496,7 +571,14 @@ def sync_templates_action(config: dict, context: dict) -> int:
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
agents_dst,
agents_src,
start_marker,
end_marker,
project_name,
date_value,
main_language,
playbook_scripts,
)
if rules_src.is_file():
@@ -506,7 +588,9 @@ def sync_templates_action(config: dict, context: dict) -> int:
else:
backup_path(rules_dst, no_backup)
text = rules_src.read_text(encoding="utf-8")
text = replace_placeholders(text, project_name, date_value)
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")
@@ -912,7 +996,11 @@ def main(argv: list[str]) -> int:
root = (config_path.parent / root).resolve()
else:
root = config_path.parent
context = {"project_root": root.resolve(), "config_path": config_path.resolve()}
context = {
"project_root": root.resolve(),
"config_path": config_path.resolve(),
"config": config,
}
for name in ORDER:
if name in config: