91 行
3.6 KiB
Python
可执行文件
91 行
3.6 KiB
Python
可执行文件
#!/usr/bin/env python3
|
|
"""Seed a target project with the workflow's standard files and directories."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import shutil
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
|
|
PLAYBOOK_FILES = {
|
|
"new-project-from-scaffold": "new-project-from-scaffold.md",
|
|
"existing-project-spec-backfill-and-refactor": "existing-project-spec-backfill-and-refactor.md",
|
|
"spec-code-alignment-gap-closure": "spec-code-alignment-gap-closure.md",
|
|
}
|
|
|
|
|
|
def copy_file(source: Path, target: Path, force: bool) -> str:
|
|
if target.exists() and not force:
|
|
return f"skip {target}"
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source, target)
|
|
return f"write {target}"
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Bootstrap a repo with the CC Switch workflow files.")
|
|
parser.add_argument("--target-dir", required=True, help="Absolute or relative project directory to seed.")
|
|
parser.add_argument("--playbook", required=True, choices=sorted(PLAYBOOK_FILES))
|
|
parser.add_argument("--force", action="store_true", help="Overwrite existing files.")
|
|
args = parser.parse_args()
|
|
|
|
skill_root = Path(__file__).resolve().parent.parent
|
|
knowledge_base = skill_root / "references" / "knowledge-base"
|
|
templates_root = knowledge_base / "templates"
|
|
playbooks_root = knowledge_base / "playbooks"
|
|
workflows_root = knowledge_base / "workflows"
|
|
target_dir = Path(args.target_dir).expanduser().resolve()
|
|
|
|
required_dirs = [
|
|
target_dir / ".meetings",
|
|
target_dir / ".research",
|
|
target_dir / ".plans",
|
|
target_dir / ".handoff",
|
|
target_dir / ".acceptance",
|
|
target_dir / ".workflow",
|
|
target_dir / ".decisions",
|
|
target_dir / "SPECS",
|
|
]
|
|
for directory in required_dirs:
|
|
directory.mkdir(parents=True, exist_ok=True)
|
|
|
|
writes = []
|
|
template_map = {
|
|
templates_root / "claude-md-template.md": target_dir / "CLAUDE.md",
|
|
templates_root / "analysis-template.md": target_dir / "ANALYSIS.md",
|
|
templates_root / "todo-yaml-template.md": target_dir / "TODO.yaml",
|
|
templates_root / "spec-template.md": target_dir / "SPECS" / "_template.md",
|
|
templates_root / "tdd-plan-template.md": target_dir / ".plans" / "_tdd-plan-template.md",
|
|
templates_root / "agent-handoff-template.md": target_dir / ".handoff" / "_agent-handoff-template.md",
|
|
templates_root / "acceptance-checklist-template.md": target_dir / ".acceptance" / "_acceptance-checklist.md",
|
|
playbooks_root / PLAYBOOK_FILES[args.playbook]: target_dir / ".workflow" / "selected-playbook.md",
|
|
workflows_root / "README.md": target_dir / ".workflow" / "stage-index.md",
|
|
knowledge_base / "README.md": target_dir / ".workflow" / "knowledge-base-overview.md",
|
|
}
|
|
|
|
for source, target in template_map.items():
|
|
writes.append(copy_file(source, target, args.force))
|
|
|
|
manifest = {
|
|
"skill": "cc-switch-dev-workflow",
|
|
"playbook": args.playbook,
|
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
"target_dir": str(target_dir),
|
|
}
|
|
manifest_path = target_dir / ".workflow" / "bootstrap-manifest.json"
|
|
if not manifest_path.exists() or args.force:
|
|
manifest_path.write_text(json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
writes.append(f"write {manifest_path}")
|
|
else:
|
|
writes.append(f"skip {manifest_path}")
|
|
|
|
print("\n".join(writes))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|