feat(playbook): auto-create CLAUDE.md with path discovery

sync_claude_md now:
- Checks project root CLAUDE.md first, then .claude/CLAUDE.md
- Auto-creates if neither exists (default: project root)
- Supports playbook.claude_md config to override location
- Update test to verify auto-creation behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
csh
2026-05-16 13:29:33 +08:00
co-authored by Claude Opus 4.6
parent 6ec9a45a83
commit 6518f0f554
2 changed files with 29 additions and 7 deletions
+23 -5
View File
@@ -721,18 +721,30 @@ def sync_agents_template(context: dict) -> int:
date_value,
playbook_scripts,
)
sync_claude_md(project_root)
sync_claude_md(project_root, context.get("config", {}))
return 0
_CLAUDE_BLOCK_START = "<!-- playbook:claude:start -->"
_CLAUDE_BLOCK_END = "<!-- playbook:claude:end -->"
_CLAUDE_MD_CANDIDATES = ["CLAUDE.md", ".claude/CLAUDE.md"]
def sync_claude_md(project_root: Path) -> None:
claude_md = project_root / "CLAUDE.md"
if not claude_md.exists():
return
def sync_claude_md(project_root: Path, config: dict) -> None:
claude_md_config = config.get("playbook", {}).get("claude_md")
claude_md: Path | None = None
if claude_md_config:
claude_md = project_root / claude_md_config
else:
for candidate in _CLAUDE_MD_CANDIDATES:
path = project_root / candidate
if path.exists():
claude_md = path
break
if claude_md is None:
claude_md = project_root / "CLAUDE.md"
block_lines = [
_CLAUDE_BLOCK_START,
@@ -743,6 +755,12 @@ def sync_claude_md(project_root: Path) -> None:
_CLAUDE_BLOCK_END,
]
if not claude_md.exists():
ensure_dir(claude_md.parent)
claude_md.write_text("\n".join(block_lines) + "\n", encoding="utf-8")
log(f"Created {claude_md.relative_to(project_root)} with playbook block.")
return
text = claude_md.read_text(encoding="utf-8")
if _CLAUDE_BLOCK_START in text: