feat(onboard): add rmgr repo-onboard, the missing managed_repos write path
hub-record-authority.yaml assigns managed_repos to repo-manager as file-derived, but repo-manager exposed no command for it. The only working path lived in the State Hub repo and defaulted to 127.0.0.1:8000, which is how seven weeks of onboarding landed in a local cache instead of central. Order follows ADR-010 decision 5: make the source file correct and reachable first, then project it. Refuses to onboard when the classification file is missing or invalid, has uncommitted changes, has no upstream, or has unpushed commits — a hub record whose backing file is only local cannot be re-derived by anyone else. --api-base has no default on purpose. A silent localhost default is the original defect, not a convenience. A failed classification PATCH degrades to a warning rather than failing the run: the authoritative record existing is what stops a repository from being recoverable only through a discardable cache, and classification is a projection of a committed file that can be re-derived later. Refs CUST-WP-0067-T04 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
This commit is contained in:
parent
885575802c
commit
1be6d85397
3 changed files with 357 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
|||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from repo_manager.commands.rapp import add_rapp_parser
|
||||
|
|
@ -76,6 +77,25 @@ def main(argv: list[str] | None = None) -> int:
|
|||
help="Rebuild all authoritative UUIDs after proving the repo projection is empty",
|
||||
)
|
||||
|
||||
p_onboard = sub.add_parser(
|
||||
"repo-onboard",
|
||||
help="Onboard a repository into its authoritative State Hub from its classification file",
|
||||
)
|
||||
p_onboard.add_argument("--path", default=".", help="Repository checkout path")
|
||||
p_onboard.add_argument("--slug", default=None, help="Override the repo slug (default: directory name)")
|
||||
p_onboard.add_argument(
|
||||
"--api-base",
|
||||
default=os.environ.get("STATE_HUB_API_BASE"),
|
||||
help="Authoritative State Hub API base URL (or set STATE_HUB_API_BASE). "
|
||||
"Deliberately has no default: a silent localhost default is how "
|
||||
"onboarding reached a cache instead of central for seven weeks.",
|
||||
)
|
||||
p_onboard.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Report what would change without writing to the hub",
|
||||
)
|
||||
|
||||
p_cmd = sub.add_parser(
|
||||
"update-task-status",
|
||||
help="Command repo.work.update_task_status (file + git commit)",
|
||||
|
|
@ -504,6 +524,29 @@ def main(argv: list[str] | None = None) -> int:
|
|||
print(json.dumps(result.to_dict(), indent=2))
|
||||
return 0 if result.status in {"applied", "noop"} else 1
|
||||
|
||||
if args.command == "repo-onboard":
|
||||
from repo_manager.commands.repo_onboard import OnboardError, onboard_repo
|
||||
|
||||
if not args.api_base:
|
||||
print(
|
||||
"ERROR: --api-base is required (or set STATE_HUB_API_BASE). "
|
||||
"Point it at the authoritative hub, not a local cache.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
try:
|
||||
report = onboard_repo(
|
||||
Path(args.path),
|
||||
api_base=args.api_base,
|
||||
dry_run=args.dry_run,
|
||||
slug=args.slug,
|
||||
)
|
||||
except OnboardError as exc:
|
||||
print(json.dumps({"status": "blocked", "error": str(exc)}, indent=2))
|
||||
return 1
|
||||
print(json.dumps(report, indent=2))
|
||||
return 0
|
||||
|
||||
if args.command == "update-task-status":
|
||||
from repo_manager.commands.task_status import update_task_status
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue