#!/usr/bin/env python3 """Training/export helpers for local control tags.""" from __future__ import annotations import json from pathlib import Path from typing import Any, Iterable def export_control_tag_jsonl( *, cache_dir: Path, tags_payload: dict[str, Any], issues_by_id: dict[int, dict[str, Any]], tag: str | None = None, out_path: Path, ) -> int: """Write one JSONL record per tagged ticket for later LLM refine / training. Each line: {tag, issue_id, subject, status, assignee, contact_email, properties, annotation, text_snippet} """ out_path = Path(out_path) out_path.parent.mkdir(parents=True, exist_ok=True) tags = tags_payload.get("tags") if isinstance(tags_payload, dict) else {} if not isinstance(tags, dict): tags = {} names = [tag] if tag else sorted(tags.keys()) count = 0 with out_path.open("w", encoding="utf-8") as fh: for name in names: bucket = tags.get(name) or {} tickets = bucket.get("tickets") if isinstance(bucket, dict) else {} if not isinstance(tickets, dict): continue for iid_s, meta in tickets.items(): try: iid = int(iid_s) except (TypeError, ValueError): continue issue = issues_by_id.get(iid) or {} helpdesk_raw = issue.get("helpdesk_ticket") helpdesk: dict[str, Any] = helpdesk_raw if isinstance(helpdesk_raw, dict) else {} contact_raw = helpdesk.get("contact") contact: dict[str, Any] = contact_raw if isinstance(contact_raw, dict) else {} status_raw = issue.get("status") status_obj: dict[str, Any] = status_raw if isinstance(status_raw, dict) else {} assignee_raw = issue.get("assigned_to") assignee_obj: dict[str, Any] = assignee_raw if isinstance(assignee_raw, dict) else {} meta_d = meta if isinstance(meta, dict) else {} rec = { "tag": name, "issue_id": iid, "subject": issue.get("subject"), "status": status_obj.get("name"), "assignee": assignee_obj.get("name"), "contact_email": contact.get("email") or helpdesk.get("from_address"), "properties": meta_d.get("properties") or [], "annotation": meta_d.get("annotation") or "", "text_snippet": ( f"{issue.get('subject') or ''}\n{(issue.get('description') or '')[:500]}" ).strip(), } fh.write(json.dumps(rec, sort_keys=True) + "\n") count += 1 return count