feat(RMGR-WP-0001): complete T05 end-to-end vertical slice
Implement observe/reconcile/update-task-status CLI path: workplan parse, JSON projection index, git-backed task status writeback with correlation events, and E2E pytest plus evidence artifacts. Finish foundation workplan.
This commit is contained in:
parent
3cc67a9bd0
commit
8b5634ff2a
15 changed files with 873 additions and 20 deletions
|
|
@ -1,9 +1,11 @@
|
|||
"""CLI entry point ``rmgr`` (skeleton — commands land with extract phases)."""
|
||||
"""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:
|
||||
|
|
@ -11,37 +13,94 @@ def main(argv: list[str] | None = None) -> int:
|
|||
prog="rmgr",
|
||||
description="Repo Manager CLI (helixforge.repo-manager)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--version",
|
||||
action="store_true",
|
||||
help="Print package version and exit",
|
||||
)
|
||||
parser.add_argument("--version", action="store_true", help="Print package version")
|
||||
sub = parser.add_subparsers(dest="command")
|
||||
|
||||
sub.add_parser("version", help="Print version")
|
||||
|
||||
# Placeholders — implemented as extraction phases land (RMGR-WP-0001-T05+).
|
||||
p_rec = sub.add_parser(
|
||||
"reconcile",
|
||||
help="Run consistency reconcile (not yet implemented)",
|
||||
)
|
||||
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("--fix", action="store_true", help="Apply safe fixes")
|
||||
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":
|
||||
print(
|
||||
"rmgr reconcile: not implemented yet "
|
||||
"(see docs/adr-001-implementation-foundation.md, phase P0)",
|
||||
file=sys.stderr,
|
||||
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"],
|
||||
},
|
||||
)
|
||||
return 2
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue