Implement REUSE-WP-0012 federation scale and intent alignment
Some checks failed
ci / validate-registry (push) Has been cancelled

Add hub sync and report cohorts CLI commands with pytest coverage, document
sibling index publish contract and hub hardening path, align INTENT layout,
raise external evidence on three registry entries, and close gap priorities
19-23 (priority 18 deferred on sibling index blocks).
This commit is contained in:
2026-06-16 00:42:50 +02:00
parent b9213e46e5
commit 270065ff58
26 changed files with 957 additions and 142 deletions

View File

@@ -13,7 +13,19 @@ from reuse_surface.catalog import write_catalog
from reuse_surface.federation import write_federated_index
from reuse_surface import hub_client
from reuse_surface.graph import check_relations, render_mermaid, write_graph
from reuse_surface.hub_sync import (
DEFAULT_SOURCES_PATH,
build_manifest,
load_sources_manifest,
write_sources_manifest,
)
from reuse_surface.overlaps import find_overlaps
from reuse_surface.reports import (
cohort_filters_from_args,
format_cohort_json,
format_cohort_markdown,
select_cohort,
)
from reuse_surface.registry import (
ROOT,
capability_paths,
@@ -294,6 +306,39 @@ def cmd_hub_update(args: argparse.Namespace) -> int:
return 0
def cmd_hub_sync(args: argparse.Namespace) -> int:
try:
status, payload = hub_client.hub_list(_service_url(args))
except ValueError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
if status != 200:
print(f"error: hub returned {status}: {payload}", file=sys.stderr)
return 1
output = Path(args.output) if args.output else DEFAULT_SOURCES_PATH
existing = load_sources_manifest(output) if args.merge else None
manifest = build_manifest(payload, existing, merge=args.merge)
if args.dry_run:
print(yaml.safe_dump(manifest, sort_keys=False))
return 0
written = write_sources_manifest(manifest, output)
print(
f"ok: wrote {written.relative_to(ROOT)} "
f"({len(manifest['sources'])} source(s))"
)
return 0
def cmd_report_cohorts(args: argparse.Namespace) -> int:
filters = cohort_filters_from_args(args)
matches = select_cohort(filters)
if args.format == "json":
print(format_cohort_json(matches, filters))
else:
print(format_cohort_markdown(matches, filters), end="")
return 0
def cmd_export(args: argparse.Namespace) -> int:
index = load_index()
bundle: dict[str, Any] = {
@@ -457,6 +502,43 @@ def main(argv: list[str] | None = None) -> int:
hub_update.add_argument("--required", action=argparse.BooleanOptionalAction, default=None)
hub_update.set_defaults(func=cmd_hub_update)
hub_sync = hub_sub.add_parser(
"sync", help="write federation sources.yaml from hub registrations"
)
hub_sync.add_argument(
"--output",
help=f"manifest path (default: {DEFAULT_SOURCES_PATH.relative_to(ROOT)})",
)
hub_sync.add_argument(
"--merge",
action="store_true",
help="keep local index sources not overridden by hub repo slugs",
)
hub_sync.add_argument(
"--dry-run",
action="store_true",
help="print manifest without writing",
)
hub_sync.set_defaults(func=cmd_hub_sync)
report = subparsers.add_parser("report", help="planning and analytics reports")
report_sub = report.add_subparsers(dest="report_command", required=True)
cohorts = report_sub.add_parser(
"cohorts", help="export capability cohorts by maturity filters"
)
cohorts.add_argument("--planning-min", help="discovery minimum (implies availability-max A1)")
cohorts.add_argument("--implementation-min", help="availability minimum")
cohorts.add_argument("--discovery-min")
cohorts.add_argument("--availability-min")
cohorts.add_argument("--availability-max")
cohorts.add_argument("--domain")
cohorts.add_argument(
"--format",
choices=["markdown", "json"],
default="markdown",
)
cohorts.set_defaults(func=cmd_report_cohorts)
args = parser.parse_args(argv)
return args.func(args)