"""CLI entry point ``rmgr``.""" from __future__ import annotations import argparse import json import sys from pathlib import Path def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser( prog="rmgr", description="Repo Manager CLI (helixforge.repo-manager)", ) parser.add_argument("--version", action="store_true", help="Print package version") sub = parser.add_subparsers(dest="command") sub.add_parser("version", help="Print version") p_obs = sub.add_parser("observe", help="Observe repository + print snapshot JSON") p_obs.add_argument("--path", default=".", help="Repository checkout path") p_obs.add_argument("--slug", default=None, help="Override repo slug") p_rec = sub.add_parser("reconcile", help="Rebuild local work-record index from files") p_rec.add_argument("--path", default=".", help="Repository checkout path") p_rec.add_argument("--slug", default=None) p_rec.add_argument( "--write-index", action="store_true", default=True, help="Write .repo-manager/index.json (default true)", ) p_rec.add_argument("--no-write-index", action="store_true", help="Do not write index file") p_cmd = sub.add_parser( "update-task-status", help="Command repo.work.update_task_status (file + git commit)", ) p_cmd.add_argument("--path", default=".", help="Repository checkout path") p_cmd.add_argument("--task-id", required=True, help="Canonical task id e.g. RMGR-WP-0001-T05") p_cmd.add_argument( "--status", required=True, choices=["wait", "todo", "progress", "done", "cancel"], ) p_cmd.add_argument("--reason", default="rmgr CLI") p_cmd.add_argument("--correlation-id", default=None) p_cmd.add_argument( "--no-commit", action="store_true", help="Patch file only (invalid as full applied evidence; for tests)", ) args = parser.parse_args(argv) if args.version or args.command in (None, "version"): from repo_manager import __version__ print(__version__) return 0 if args.command or args.version else 0 if args.command == "observe": from repo_manager.observe import observe_repository snap, _idx = observe_repository(Path(args.path), slug=args.slug) print(json.dumps(snap, indent=2)) return 0 if args.command == "reconcile": from repo_manager.index_store import append_event, save_index from repo_manager.observe import observe_repository root = Path(args.path) snap, index = observe_repository(root, slug=args.slug) append_event( index, { "type": "repo.reconciled", "workplan_count": snap["index"]["workplan_count"], "task_count": snap["index"]["task_count"], }, ) if not args.no_write_index: path = save_index(index) print(json.dumps({"ok": True, "index_path": str(path), "snapshot": snap}, indent=2)) else: print(json.dumps({"ok": True, "snapshot": snap, "index": index.to_dict()}, indent=2)) return 0 if args.command == "update-task-status": from repo_manager.commands.task_status import update_task_status result = update_task_status( Path(args.path), args.task_id, args.status, correlation_id=args.correlation_id, reason=args.reason, commit=not args.no_commit, ) print(json.dumps(result.to_dict(), indent=2)) return 0 if result.status == "applied" else 1 parser.print_help() return 0 if __name__ == "__main__": raise SystemExit(main())