✨ feat(playbook): add playbook root boundary placeholder
This commit is contained in:
parent
f2ab57b39f
commit
02ad5e5f4a
|
|
@ -626,10 +626,13 @@ def replace_placeholders(
|
||||||
project_name: str | None,
|
project_name: str | None,
|
||||||
date_value: str,
|
date_value: str,
|
||||||
playbook_scripts: str | None,
|
playbook_scripts: str | None,
|
||||||
|
playbook_root: str | None,
|
||||||
) -> str:
|
) -> str:
|
||||||
result = text.replace("{{DATE}}", date_value)
|
result = text.replace("{{DATE}}", date_value)
|
||||||
if project_name:
|
if project_name:
|
||||||
result = result.replace("{{PROJECT_NAME}}", project_name)
|
result = result.replace("{{PROJECT_NAME}}", project_name)
|
||||||
|
if playbook_root:
|
||||||
|
result = result.replace("{{PLAYBOOK_ROOT}}", playbook_root)
|
||||||
if playbook_scripts:
|
if playbook_scripts:
|
||||||
result = result.replace("{{PLAYBOOK_SCRIPTS}}", playbook_scripts)
|
result = result.replace("{{PLAYBOOK_SCRIPTS}}", playbook_scripts)
|
||||||
return result
|
return result
|
||||||
|
|
@ -649,11 +652,14 @@ def replace_placeholders_in_file(
|
||||||
project_name: str | None,
|
project_name: str | None,
|
||||||
date_value: str,
|
date_value: str,
|
||||||
playbook_scripts: str | None,
|
playbook_scripts: str | None,
|
||||||
|
playbook_root: str | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
if file_path.suffix != ".md":
|
if file_path.suffix != ".md":
|
||||||
return
|
return
|
||||||
text = file_path.read_text(encoding="utf-8")
|
text = file_path.read_text(encoding="utf-8")
|
||||||
updated = replace_placeholders(text, project_name, date_value, playbook_scripts)
|
updated = replace_placeholders(
|
||||||
|
text, project_name, date_value, playbook_scripts, playbook_root
|
||||||
|
)
|
||||||
if updated != text:
|
if updated != text:
|
||||||
file_path.write_text(updated, encoding="utf-8", newline="\n")
|
file_path.write_text(updated, encoding="utf-8", newline="\n")
|
||||||
|
|
||||||
|
|
@ -673,6 +679,7 @@ def sync_directory(
|
||||||
project_name: str | None,
|
project_name: str | None,
|
||||||
date_value: str,
|
date_value: str,
|
||||||
playbook_scripts: str | None,
|
playbook_scripts: str | None,
|
||||||
|
playbook_root: str | None,
|
||||||
force: bool,
|
force: bool,
|
||||||
no_backup: bool,
|
no_backup: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
@ -693,6 +700,7 @@ def sync_directory(
|
||||||
project_name,
|
project_name,
|
||||||
date_value,
|
date_value,
|
||||||
playbook_scripts,
|
playbook_scripts,
|
||||||
|
playbook_root,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -720,10 +728,11 @@ def update_agents_section(
|
||||||
project_name: str | None,
|
project_name: str | None,
|
||||||
date_value: str,
|
date_value: str,
|
||||||
playbook_scripts: str | None,
|
playbook_scripts: str | None,
|
||||||
|
playbook_root: str | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
template_text = template_path.read_text(encoding="utf-8")
|
template_text = template_path.read_text(encoding="utf-8")
|
||||||
template_text = replace_placeholders(
|
template_text = replace_placeholders(
|
||||||
template_text, project_name, date_value, playbook_scripts
|
template_text, project_name, date_value, playbook_scripts, playbook_root
|
||||||
)
|
)
|
||||||
block = extract_block_lines(template_text, start_marker, end_marker)
|
block = extract_block_lines(template_text, start_marker, end_marker)
|
||||||
if not block:
|
if not block:
|
||||||
|
|
@ -802,6 +811,7 @@ def sync_agents_template(context: dict) -> int:
|
||||||
|
|
||||||
project_name = resolve_project_name(context)
|
project_name = resolve_project_name(context)
|
||||||
playbook_scripts = resolve_playbook_scripts(context)
|
playbook_scripts = resolve_playbook_scripts(context)
|
||||||
|
playbook_root = resolve_playbook_root(context)
|
||||||
date_value = resolve_template_date(context)
|
date_value = resolve_template_date(context)
|
||||||
|
|
||||||
agents_dst = project_root / "AGENTS.md"
|
agents_dst = project_root / "AGENTS.md"
|
||||||
|
|
@ -828,6 +838,7 @@ def sync_agents_template(context: dict) -> int:
|
||||||
project_name,
|
project_name,
|
||||||
date_value,
|
date_value,
|
||||||
playbook_scripts,
|
playbook_scripts,
|
||||||
|
playbook_root,
|
||||||
)
|
)
|
||||||
sync_claude_md(project_root, context.get("config", {}))
|
sync_claude_md(project_root, context.get("config", {}))
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -944,12 +955,15 @@ def sync_rules_action(config: dict, context: dict) -> int:
|
||||||
|
|
||||||
project_name = resolve_project_name(context)
|
project_name = resolve_project_name(context)
|
||||||
playbook_scripts = resolve_playbook_scripts(context)
|
playbook_scripts = resolve_playbook_scripts(context)
|
||||||
|
playbook_root = resolve_playbook_root(context)
|
||||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||||
no_backup = bool(config.get("no_backup", False))
|
no_backup = bool(config.get("no_backup", False))
|
||||||
|
|
||||||
backup_path(rules_dst, no_backup)
|
backup_path(rules_dst, no_backup)
|
||||||
text = rules_src.read_text(encoding="utf-8")
|
text = rules_src.read_text(encoding="utf-8")
|
||||||
text = replace_placeholders(text, project_name, date_value, playbook_scripts)
|
text = replace_placeholders(
|
||||||
|
text, project_name, date_value, playbook_scripts, playbook_root
|
||||||
|
)
|
||||||
rules_dst.write_text(text.rstrip("\n") + "\n", encoding="utf-8", newline="\n")
|
rules_dst.write_text(text.rstrip("\n") + "\n", encoding="utf-8", newline="\n")
|
||||||
log("Synced: AGENT_RULES.md")
|
log("Synced: AGENT_RULES.md")
|
||||||
|
|
||||||
|
|
@ -987,6 +1001,7 @@ def sync_memory_bank_action(config: dict, context: dict) -> int:
|
||||||
|
|
||||||
project_name = config.get("project_name")
|
project_name = config.get("project_name")
|
||||||
playbook_scripts = resolve_playbook_scripts(context)
|
playbook_scripts = resolve_playbook_scripts(context)
|
||||||
|
playbook_root = resolve_playbook_root(context)
|
||||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||||
force = bool(config.get("force", False))
|
force = bool(config.get("force", False))
|
||||||
no_backup = bool(config.get("no_backup", False))
|
no_backup = bool(config.get("no_backup", False))
|
||||||
|
|
@ -999,6 +1014,7 @@ def sync_memory_bank_action(config: dict, context: dict) -> int:
|
||||||
project_name,
|
project_name,
|
||||||
date_value,
|
date_value,
|
||||||
playbook_scripts,
|
playbook_scripts,
|
||||||
|
playbook_root,
|
||||||
force,
|
force,
|
||||||
no_backup,
|
no_backup,
|
||||||
)
|
)
|
||||||
|
|
@ -1020,6 +1036,7 @@ def sync_prompts_action(config: dict, context: dict) -> int:
|
||||||
|
|
||||||
project_name = resolve_project_name(context)
|
project_name = resolve_project_name(context)
|
||||||
playbook_scripts = resolve_playbook_scripts(context)
|
playbook_scripts = resolve_playbook_scripts(context)
|
||||||
|
playbook_root = resolve_playbook_root(context)
|
||||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||||
force = bool(config.get("force", False))
|
force = bool(config.get("force", False))
|
||||||
no_backup = bool(config.get("no_backup", False))
|
no_backup = bool(config.get("no_backup", False))
|
||||||
|
|
@ -1033,6 +1050,7 @@ def sync_prompts_action(config: dict, context: dict) -> int:
|
||||||
project_name,
|
project_name,
|
||||||
date_value,
|
date_value,
|
||||||
playbook_scripts,
|
playbook_scripts,
|
||||||
|
playbook_root,
|
||||||
force,
|
force,
|
||||||
no_backup,
|
no_backup,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,23 @@
|
||||||
- 只做当前任务需要的改动,不顺手加功能、不顺手重构
|
- 只做当前任务需要的改动,不顺手加功能、不顺手重构
|
||||||
- 不为一次性操作增加抽象,不为假设的未来需求设计
|
- 不为一次性操作增加抽象,不为假设的未来需求设计
|
||||||
|
|
||||||
|
## 项目边界
|
||||||
|
|
||||||
|
### Playbook 目录
|
||||||
|
|
||||||
|
- `{{PLAYBOOK_ROOT}}/` 是 Playbook 模板/供应商目录,不是业务项目源码、
|
||||||
|
业务文档或当前项目私有规则
|
||||||
|
- 除非用户明确要求维护、升级或调试 Playbook 本身,不得修改
|
||||||
|
`{{PLAYBOOK_ROOT}}/` 下内容
|
||||||
|
- 当前项目已生效的规则入口是项目根目录的 `AGENT_RULES.md`、
|
||||||
|
`AGENT_RULES.local.md`、`AGENTS.md` 与 `.agents/`
|
||||||
|
- `{{PLAYBOOK_ROOT}}/templates/` 与 `{{PLAYBOOK_ROOT}}/rulesets/`
|
||||||
|
是模板源;不要把它们当作当前项目已生效规则
|
||||||
|
- 可按 `.agents/` 指向读取 `{{PLAYBOOK_ROOT}}/docs/` 作为标准文档;
|
||||||
|
读取不代表该目录属于业务改动范围
|
||||||
|
- 搜索、批量修改、代码审查、归档/提交时,默认排除 `{{PLAYBOOK_ROOT}}/`;
|
||||||
|
只有任务目标明确涉及 Playbook 时才纳入
|
||||||
|
|
||||||
## 会话启动
|
## 会话启动
|
||||||
|
|
||||||
每次新会话开始时,按顺序加载以下上下文:
|
每次新会话开始时,按顺序加载以下上下文:
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ python scripts/playbook.py -config playbook.toml
|
||||||
- **force**:默认 false,已存在则跳过;设为 true 时覆盖框架文件(会先备份)
|
- **force**:默认 false,已存在则跳过;设为 true 时覆盖框架文件(会先备份)
|
||||||
- **no_backup**:默认 false;设为 true 时跳过备份直接覆盖
|
- **no_backup**:默认 false;设为 true 时跳过备份直接覆盖
|
||||||
- **不删除项目文件**:只更新框架提供的文件,项目新增的文件不会被删除
|
- **不删除项目文件**:只更新框架提供的文件,项目新增的文件不会被删除
|
||||||
- **占位符替换**:自动替换 `{{DATE}}`、`{{PROJECT_NAME}}`、`{{PLAYBOOK_SCRIPTS}}`
|
- **占位符替换**:自动替换 `{{DATE}}`、`{{PROJECT_NAME}}`、`{{PLAYBOOK_ROOT}}`、`{{PLAYBOOK_SCRIPTS}}`
|
||||||
|
|
||||||
### 典型场景
|
### 典型场景
|
||||||
|
|
||||||
|
|
@ -229,11 +229,15 @@ project/
|
||||||
| `{{PROJECT_NAME}}` | 项目名称 | ✅ 可选 |
|
| `{{PROJECT_NAME}}` | 项目名称 | ✅ 可选 |
|
||||||
| `{{PROJECT_GOAL}}` | 项目目标 | ❌ 手动 |
|
| `{{PROJECT_GOAL}}` | 项目目标 | ❌ 手动 |
|
||||||
| `{{PROJECT_DESCRIPTION}}` | 项目描述 | ❌ 手动 |
|
| `{{PROJECT_DESCRIPTION}}` | 项目描述 | ❌ 手动 |
|
||||||
|
| `{{PLAYBOOK_ROOT}}` | Playbook 根 | ✅ 是 |
|
||||||
| `{{PLAYBOOK_SCRIPTS}}` | 脚本路径 | ✅ 是 |
|
| `{{PLAYBOOK_SCRIPTS}}` | 脚本路径 | ✅ 是 |
|
||||||
| 其他 `{{...}}` | 项目特定内容 | ❌ 手动 |
|
| 其他 `{{...}}` | 项目特定内容 | ❌ 手动 |
|
||||||
|
|
||||||
`{{PROJECT_NAME}}` 可通过 `sync_memory_bank.project_name` 自动替换;
|
`{{PROJECT_NAME}}` 可通过 `sync_memory_bank.project_name` 自动替换;
|
||||||
未配置时保持原样。
|
未配置时保持原样。
|
||||||
|
`{{PLAYBOOK_ROOT}}` 自动替换为项目内 Playbook 根目录
|
||||||
|
(默认 `docs/standards/playbook`,
|
||||||
|
也可按项目配置改成 `custom/playbook` 等)。
|
||||||
`{{PLAYBOOK_SCRIPTS}}` 自动替换为 Playbook 脚本路径
|
`{{PLAYBOOK_SCRIPTS}}` 自动替换为 Playbook 脚本路径
|
||||||
(默认 `docs/standards/playbook/scripts`,
|
(默认 `docs/standards/playbook/scripts`,
|
||||||
也可按项目配置改成 `custom/playbook/scripts` 等)。
|
也可按项目配置改成 `custom/playbook/scripts` 等)。
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue