From b548568b42365dca9559792a008cdc2c636c09fe Mon Sep 17 00:00:00 2001 From: Joe Qiu <39745128+josephmqiu@users.noreply.github.com> Date: Thu, 2 Jul 2026 09:58:33 +0800 Subject: [PATCH] Add missing 'backup' action to version_manager.py SKILL.md's evolution flow (zh line 318 / en line 587) invokes 'version_manager.py --action backup' before applying updates, but the action was never implemented (argparse choices only had list/rollback/cleanup), so the archive step always exited with code 2 and rollback had nothing to restore. Implements backup(): reads the current version from meta.json, copies SKILL.md/memories.md/persona.md into versions/{current_version}/, and reports what was archived. Mirrors the archive logic already present in skill_writer.update_skill(). Fixes #25 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Qxv8G25EYkYzQyY6FdJ6qH --- tools/version_manager.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/tools/version_manager.py b/tools/version_manager.py index 53b9bd2..440586f 100644 --- a/tools/version_manager.py +++ b/tools/version_manager.py @@ -5,6 +5,7 @@ 负责 Skill 文件的版本存档和回滚。 用法: + python version_manager.py --action backup --slug xiaomei --base-dir ./exes python version_manager.py --action list --slug xiaomei --base-dir ./exes python version_manager.py --action rollback --slug xiaomei --version v2 --base-dir ./exes """ @@ -47,6 +48,30 @@ def list_versions(skill_dir: Path) -> list: return versions +def backup(skill_dir: Path) -> Path | None: + """存档当前版本到 versions/{current_version}/""" + meta_path = skill_dir / "meta.json" + if not meta_path.exists(): + print(f"错误:找不到 {meta_path},无法确定当前版本", file=sys.stderr) + return None + + meta = json.loads(meta_path.read_text(encoding="utf-8")) + current_version = meta.get("version", "v1") + + backup_dir = skill_dir / "versions" / current_version + backup_dir.mkdir(parents=True, exist_ok=True) + + backed_up = [] + for fname in ("SKILL.md", "memories.md", "persona.md"): + src = skill_dir / fname + if src.exists(): + shutil.copy2(src, backup_dir / fname) + backed_up.append(fname) + + print(f"已存档当前版本({current_version})到 {backup_dir},文件:{', '.join(backed_up) if backed_up else '无'}") + return backup_dir + + def rollback(skill_dir: Path, target_version: str) -> bool: """回滚到指定版本""" version_dir = skill_dir / "versions" / target_version @@ -107,7 +132,7 @@ def cleanup_old_versions(skill_dir: Path, max_versions: int = MAX_VERSIONS): def main(): parser = argparse.ArgumentParser(description="Skill 版本管理器") - parser.add_argument("--action", required=True, choices=["list", "rollback", "cleanup"]) + parser.add_argument("--action", required=True, choices=["backup", "list", "rollback", "cleanup"]) parser.add_argument("--slug", required=True, help="前任 slug") parser.add_argument("--version", help="目标版本号(rollback 时使用)") parser.add_argument( @@ -124,7 +149,11 @@ def main(): print(f"错误:找不到 Skill 目录 {skill_dir}", file=sys.stderr) sys.exit(1) - if args.action == "list": + if args.action == "backup": + if backup(skill_dir) is None: + sys.exit(1) + + elif args.action == "list": versions = list_versions(skill_dir) if not versions: print(f"{args.slug} 暂无历史版本")