feat: advance conformance and deterministic ID migration

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
tegwick 2026-08-21 22:43:37 +02:00
parent 3791411591
commit ad621d6c0d
10 changed files with 513 additions and 20 deletions

View file

@ -286,6 +286,14 @@ def main(argv: list[str] | None = None) -> int:
p_id_derive.add_argument("--record-id", required=True)
p_id_preflight = identifier_sub.add_parser("preflight", help="Scan live identifier collisions")
p_id_preflight.add_argument("--root", default=".")
p_id_plan = identifier_sub.add_parser(
"migration-plan",
help="Emit a non-mutating, per-repository old-to-derived UUID plan",
)
p_id_plan.add_argument("--root", default=".")
p_id_plan.add_argument("--namespace", required=True)
p_id_plan.add_argument("--output", default=None, help="Write the provenance mapping as JSON")
p_id_plan.add_argument("--force", action="store_true", help="Replace an existing --output file")
args = parser.parse_args(argv)
@ -569,7 +577,11 @@ def main(argv: list[str] | None = None) -> int:
if not args.identifier_command:
p_identifier.print_help()
return 2
from repo_manager.identifiers import derive_work_record_uuid, scan_live_identifier_collisions
from repo_manager.identifiers import (
derive_work_record_uuid,
plan_identifier_migration,
scan_live_identifier_collisions,
)
if args.identifier_command == "derive":
try:
@ -583,8 +595,26 @@ def main(argv: list[str] | None = None) -> int:
"record_id": args.record_id,
"uuid": str(derived),
}
else:
elif args.identifier_command == "preflight":
result = scan_live_identifier_collisions(Path(args.root))
else:
try:
result = plan_identifier_migration(Path(args.root), args.namespace)
except ValueError as exc:
print(json.dumps({"ok": False, "error": str(exc)}, indent=2))
return 1
if args.output:
output = Path(args.output)
if output.exists() and not args.force:
print(
json.dumps(
{"ok": False, "error": f"output exists: {output}; use --force to replace"},
indent=2,
)
)
return 1
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
print(json.dumps(result, indent=2))
return 0 if result.get("ok") else 1