📝 docs(playbook): drop docs/plans snapshots
This commit is contained in:
parent
398696c9c2
commit
ab0dd11afc
|
|
@ -1,55 +0,0 @@
|
||||||
# Unified Playbook CLI Design
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
- 提供单一入口 `scripts/playbook.py`,以 TOML 配置驱动所有动作。
|
|
||||||
- 取消旧的 sh/ps1/bat 脚本与参数兼容,减少心智负担。
|
|
||||||
- 保持功能覆盖:vendoring、同步模板、同步标准、安装 skills、格式化 Markdown。
|
|
||||||
|
|
||||||
## 非目标
|
|
||||||
|
|
||||||
- 不保留旧脚本的参数兼容层。
|
|
||||||
- 不引入新的依赖(Markdown 格式化仅使用已有 Prettier)。
|
|
||||||
|
|
||||||
## CLI 设计
|
|
||||||
|
|
||||||
- 入口:`python scripts/playbook.py -config <path>`。
|
|
||||||
- 仅支持两个参数:`-config`(必填)与 `-h/-help`。
|
|
||||||
- `project_root` 默认取配置文件所在目录。
|
|
||||||
|
|
||||||
## TOML 结构
|
|
||||||
|
|
||||||
- 通过 section 是否存在决定是否执行:
|
|
||||||
- `[vendor]`
|
|
||||||
- `[sync_templates]`
|
|
||||||
- `[sync_standards]`
|
|
||||||
- `[install_skills]`
|
|
||||||
- `[format_md]`
|
|
||||||
- 固定执行顺序(不支持 step list):
|
|
||||||
`vendor → sync_templates → sync_standards → install_skills → format_md`。
|
|
||||||
|
|
||||||
## 行为要点
|
|
||||||
|
|
||||||
- `vendor` 仅生成快照,不再隐式触发 `sync_standards`。
|
|
||||||
- `sync_standards` 负责 `.agents/`、`AGENTS.md` 区块与 `.gitattributes`。
|
|
||||||
- `sync_templates` 负责 memory-bank、docs/prompts、AGENTS/AGENT_RULES 模板。
|
|
||||||
- `install_skills` 将 `codex/skills` 复制到目标 `~/.codex` 或指定路径。
|
|
||||||
- `format_md` 仅调用已有 Prettier(可通过 globs 指定范围)。
|
|
||||||
|
|
||||||
## 预期输出
|
|
||||||
|
|
||||||
- 新增:`scripts/playbook.py`、`playbook.toml.example`。
|
|
||||||
- 删除:旧的 sh/ps1/bat 脚本与对应测试。
|
|
||||||
- 更新:README/模板说明/CI/test.yml。
|
|
||||||
|
|
||||||
## 测试策略
|
|
||||||
|
|
||||||
- 用 Python `unittest` 覆盖核心路径:
|
|
||||||
- TOML 解析与动作触发顺序。
|
|
||||||
- vendor/sync 模拟执行与关键输出文件检查。
|
|
||||||
- 保留现有模板验证与文档链接检查。
|
|
||||||
|
|
||||||
## 风险
|
|
||||||
|
|
||||||
- 旧脚本移除会影响现有用户;通过 README 与示例配置降低迁移成本。
|
|
||||||
- Windows 环境权限可能影响 `npm install` 与符号链接;测试不依赖 npm。
|
|
||||||
|
|
@ -1,408 +0,0 @@
|
||||||
# Unified Playbook CLI Implementation Plan
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**Goal:** Replace legacy sh/ps1/bat scripts with a single Python CLI driven by TOML config, and update docs/tests/CI accordingly.
|
|
||||||
|
|
||||||
**Architecture:** `scripts/playbook.py` reads `playbook.toml`, validates config, then executes actions in a fixed order based on section presence. Actions are implemented as pure-Python helpers to keep cross-platform behavior.
|
|
||||||
|
|
||||||
**Tech Stack:** Python 3.11 (`tomllib`), standard library only; Prettier via local install if available.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Create CLI test harness and basic argument handling
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `tests/cli/test_playbook_cli.py`
|
|
||||||
- Modify: `tests/README.md`
|
|
||||||
|
|
||||||
**Step 1: Write failing tests for CLI usage/exit codes**
|
|
||||||
|
|
||||||
```python
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
|
||||||
SCRIPT = ROOT / "scripts" / "playbook.py"
|
|
||||||
|
|
||||||
|
|
||||||
def run(*args):
|
|
||||||
return subprocess.run([sys.executable, str(SCRIPT), *args], capture_output=True, text=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_help_shows_usage():
|
|
||||||
result = run("-h")
|
|
||||||
assert result.returncode == 0
|
|
||||||
assert "Usage:" in result.stderr or "Usage:" in result.stdout
|
|
||||||
|
|
||||||
|
|
||||||
def test_missing_config_is_error():
|
|
||||||
result = run()
|
|
||||||
assert result.returncode != 0
|
|
||||||
assert "-config" in (result.stderr + result.stdout)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Run tests to verify failure**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: FAIL (script missing)
|
|
||||||
|
|
||||||
**Step 3: Implement minimal CLI skeleton**
|
|
||||||
|
|
||||||
```python
|
|
||||||
# scripts/playbook.py
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def usage():
|
|
||||||
return "Usage:\n python scripts/playbook.py -config <path>\n python scripts/playbook.py -h"
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
|
||||||
if "-h" in argv or "-help" in argv:
|
|
||||||
print(usage())
|
|
||||||
return 0
|
|
||||||
if "-config" not in argv:
|
|
||||||
print("ERROR: -config is required.\n" + usage(), file=sys.stderr)
|
|
||||||
return 2
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main(sys.argv[1:]))
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Run tests to verify pass**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add scripts/playbook.py tests/cli/test_playbook_cli.py tests/README.md
|
|
||||||
git commit -m ":white_check_mark: test(cli): add basic playbook cli tests"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 2: Parse TOML config and enforce dispatch order
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Modify: `scripts/playbook.py`
|
|
||||||
- Create: `playbook.toml.example`
|
|
||||||
- Modify: `README.md`
|
|
||||||
|
|
||||||
**Step 1: Write failing test for TOML parsing + action order**
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_action_order(tmp_path):
|
|
||||||
config = tmp_path / "playbook.toml"
|
|
||||||
config.write_text("""
|
|
||||||
[playbook]
|
|
||||||
project_root = "."
|
|
||||||
|
|
||||||
[format_md]
|
|
||||||
|
|
||||||
[sync_standards]
|
|
||||||
langs = ["tsl"]
|
|
||||||
""")
|
|
||||||
result = run("-config", str(config))
|
|
||||||
assert result.returncode == 0
|
|
||||||
# Expect order: vendor -> sync_templates -> sync_standards -> install_skills -> format_md
|
|
||||||
# Only sections present should log as executed.
|
|
||||||
assert "sync_standards" in result.stdout
|
|
||||||
assert "format_md" in result.stdout
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Run test to verify failure**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: FAIL (no TOML parser/action logs)
|
|
||||||
|
|
||||||
**Step 3: Implement TOML parser + order dispatch**
|
|
||||||
|
|
||||||
```python
|
|
||||||
import tomllib
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
ORDER = ["vendor", "sync_templates", "sync_standards", "install_skills", "format_md"]
|
|
||||||
|
|
||||||
|
|
||||||
def load_config(path: Path) -> dict:
|
|
||||||
return tomllib.loads(path.read_text(encoding="utf-8"))
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
|
||||||
# parse -config value
|
|
||||||
# load config
|
|
||||||
# for section in ORDER: if section in config, call action
|
|
||||||
# print "[action] ..." for visibility
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Run test to verify pass**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add scripts/playbook.py playbook.toml.example README.md
|
|
||||||
git commit -m ":sparkles: feat(cli): add toml config and dispatch order"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 3: Implement `vendor` action (snapshot only)
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Modify: `scripts/playbook.py`
|
|
||||||
- Modify: `playbook.toml.example`
|
|
||||||
- Modify: `README.md`
|
|
||||||
|
|
||||||
**Step 1: Write failing test for vendoring output**
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_vendor_creates_snapshot(tmp_path):
|
|
||||||
config = tmp_path / "playbook.toml"
|
|
||||||
config.write_text("""
|
|
||||||
[playbook]
|
|
||||||
project_root = "{root}"
|
|
||||||
|
|
||||||
[vendor]
|
|
||||||
langs = ["tsl"]
|
|
||||||
""".format(root=tmp_path))
|
|
||||||
result = run("-config", str(config))
|
|
||||||
assert result.returncode == 0
|
|
||||||
assert (tmp_path / "docs/standards/playbook/SOURCE.md").is_file()
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Run test to verify failure**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: FAIL (vendor not implemented)
|
|
||||||
|
|
||||||
**Step 3: Implement vendor snapshot copy**
|
|
||||||
|
|
||||||
```python
|
|
||||||
from shutil import copy2, copytree
|
|
||||||
|
|
||||||
# Copy: scripts/, codex/, rulesets/, docs/common, docs/<lang>, templates/ci, templates/<lang>
|
|
||||||
# Generate docs/index.md, README.md, SOURCE.md
|
|
||||||
# Backup existing snapshot with timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Run test to verify pass**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add scripts/playbook.py playbook.toml.example README.md tests/cli/test_playbook_cli.py
|
|
||||||
git commit -m ":sparkles: feat(vendor): add playbook snapshot generation"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 4: Implement `sync_templates` and `sync_standards`
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Modify: `scripts/playbook.py`
|
|
||||||
- Modify: `playbook.toml.example`
|
|
||||||
- Modify: `templates/README.md`
|
|
||||||
|
|
||||||
**Step 1: Add failing tests for template sync + standards sync**
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_sync_templates_creates_memory_bank(tmp_path):
|
|
||||||
config = tmp_path / "playbook.toml"
|
|
||||||
config.write_text("""
|
|
||||||
[playbook]
|
|
||||||
project_root = "{root}"
|
|
||||||
|
|
||||||
[sync_templates]
|
|
||||||
project_name = "Demo"
|
|
||||||
""".format(root=tmp_path))
|
|
||||||
result = run("-config", str(config))
|
|
||||||
assert result.returncode == 0
|
|
||||||
assert (tmp_path / "memory-bank" / "project-brief.md").is_file()
|
|
||||||
|
|
||||||
|
|
||||||
def test_sync_standards_creates_agents(tmp_path):
|
|
||||||
config = tmp_path / "playbook.toml"
|
|
||||||
config.write_text("""
|
|
||||||
[playbook]
|
|
||||||
project_root = "{root}"
|
|
||||||
|
|
||||||
[sync_standards]
|
|
||||||
langs = ["tsl"]
|
|
||||||
""".format(root=tmp_path))
|
|
||||||
result = run("-config", str(config))
|
|
||||||
assert result.returncode == 0
|
|
||||||
assert (tmp_path / ".agents" / "tsl" / "index.md").is_file()
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Run tests to verify failure**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: FAIL
|
|
||||||
|
|
||||||
**Step 3: Implement `sync_templates`**
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Copy templates/memory-bank -> <root>/memory-bank (rename *.template.md)
|
|
||||||
# Copy templates/prompts -> <root>/docs/prompts (rename *.template.md)
|
|
||||||
# Copy AGENTS.template.md -> AGENTS.md (merge/append section)
|
|
||||||
# Copy AGENT_RULES.template.md -> AGENT_RULES.md (backup optional)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Implement `sync_standards`**
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Copy rulesets/<lang> -> <root>/.agents/<lang>
|
|
||||||
# Update AGENTS.md playbook block (robust to blank lines)
|
|
||||||
# Update .gitattributes according to gitattr_mode
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 5: Run tests to verify pass**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 6: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add scripts/playbook.py playbook.toml.example templates/README.md tests/cli/test_playbook_cli.py
|
|
||||||
git commit -m ":sparkles: feat(sync): add templates and standards actions"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 5: Implement `install_skills` and `format_md`
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Modify: `scripts/playbook.py`
|
|
||||||
- Modify: `playbook.toml.example`
|
|
||||||
- Modify: `README.md`
|
|
||||||
|
|
||||||
**Step 1: Add failing tests for skills install + md format**
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_install_skills(tmp_path):
|
|
||||||
config = tmp_path / "playbook.toml"
|
|
||||||
target = tmp_path / "codex"
|
|
||||||
config.write_text(f"""
|
|
||||||
[playbook]
|
|
||||||
project_root = "{tmp_path}"
|
|
||||||
|
|
||||||
[install_skills]
|
|
||||||
codex_home = "{target}"
|
|
||||||
mode = "list"
|
|
||||||
skills = ["brainstorming"]
|
|
||||||
""")
|
|
||||||
result = run("-config", str(config))
|
|
||||||
assert result.returncode == 0
|
|
||||||
assert (target / "skills" / "brainstorming" / "SKILL.md").is_file()
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Run tests to verify failure**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: FAIL
|
|
||||||
|
|
||||||
**Step 3: Implement `install_skills` and `format_md`**
|
|
||||||
|
|
||||||
```python
|
|
||||||
# install_skills: copy codex/skills/<name> -> <codex_home>/skills/<name>
|
|
||||||
# format_md: call `prettier` with configured globs if available
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Run tests to verify pass**
|
|
||||||
|
|
||||||
Run: `python -m unittest tests/cli/test_playbook_cli.py -v`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add scripts/playbook.py playbook.toml.example tests/cli/test_playbook_cli.py README.md
|
|
||||||
git commit -m ":sparkles: feat(actions): add install_skills and format_md"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 6: Remove legacy scripts and update CI/test docs
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Delete: `scripts/*.sh`, `scripts/*.ps1`, `scripts/*.bat`
|
|
||||||
- Delete: `tests/scripts/*.bats`
|
|
||||||
- Modify: `.gitea/workflows/test.yml`
|
|
||||||
- Modify: `tests/README.md`
|
|
||||||
- Modify: `README.md`, `templates/README.md`
|
|
||||||
|
|
||||||
**Step 1: Remove legacy scripts and obsolete tests**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
rm scripts/*.sh scripts/*.ps1 scripts/*.bat
|
|
||||||
rm tests/scripts/*.bats
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Update CI to run new Python tests + existing template/link checks**
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- name: Run CLI tests
|
|
||||||
run: python -m unittest discover -s tests/cli -v
|
|
||||||
- name: Validate templates
|
|
||||||
run: |
|
|
||||||
sh tests/templates/validate_python_templates.sh
|
|
||||||
sh tests/templates/validate_cpp_templates.sh
|
|
||||||
sh tests/templates/validate_ci_templates.sh
|
|
||||||
sh tests/templates/validate_project_templates.sh
|
|
||||||
- name: Check doc links
|
|
||||||
run: sh tests/integration/check_doc_links.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 3: Update docs to new CLI + TOML**
|
|
||||||
|
|
||||||
- Replace old script usage with `python scripts/playbook.py -config playbook.toml`.
|
|
||||||
- Document config sections and example file name.
|
|
||||||
|
|
||||||
**Step 4: Run full test suite**
|
|
||||||
|
|
||||||
Run: `python -m unittest discover -s tests/cli -v && sh tests/templates/validate_project_templates.sh && sh tests/integration/check_doc_links.sh`
|
|
||||||
Expected: PASS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add .
|
|
||||||
git commit -m ":wastebasket: remove(legacy): drop old scripts and tests"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 7: Final cleanup and formatting
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Modify: `README.md`, `templates/README.md`, `tests/README.md`
|
|
||||||
|
|
||||||
**Step 1: Run Markdown format (exclude third-party skills)**
|
|
||||||
|
|
||||||
Run: `npm run format:md -- --ignore-path .prettierignore`
|
|
||||||
Expected: No unexpected diffs
|
|
||||||
|
|
||||||
**Step 2: Commit formatting-only changes (if any)**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add README.md templates/README.md tests/README.md
|
|
||||||
git commit -m ":art: style(docs): format markdown"
|
|
||||||
```
|
|
||||||
Loading…
Reference in New Issue