"""Run the formal single-item decode workflow. This CLI is intentionally thin. Production loading should come from the formal candidate item repository; fixture loading is kept only for local smoke checks. """ from __future__ import annotations import argparse import json from pathlib import Path from uuid import UUID, uuid4 from acquisition.crawler import parse_detail_response from core.config import Settings from decode_content.service import DecodeService ROOT = Path(__file__).resolve().parent.parent def _load_fixture(path: Path): payload = json.loads(path.read_text(encoding="utf-8")) return parse_detail_response(payload, fallback_content_id=path.stem.removeprefix("xhs_case_")) def main() -> None: parser = argparse.ArgumentParser(description="Decode one creation candidate through decode_content.") parser.add_argument("--fixture", type=Path, help="local fixture JSON for smoke runs") parser.add_argument("--item-id", help="candidate item UUID; generated when omitted for fixture smoke") args = parser.parse_args() if not args.fixture: parser.error("formal DB item loading is wired in pipeline Step 6; pass --fixture for local smoke") item_id = UUID(args.item_id) if args.item_id else uuid4() post = _load_fixture(args.fixture if args.fixture.is_absolute() else ROOT / args.fixture) service = DecodeService(settings=Settings.from_env()) output = service.decode_post(item_id=item_id, post=post) print(json.dumps({"item_id": str(item_id), "status": output.status, "payload_count": len(output.payloads)}, ensure_ascii=False)) if __name__ == "__main__": main()