"""Data controls tab: model-improvement switch (read-only otherwise). The switch label is pinned from live recon; resolution prefers it and falls back to single-switch, then keyword match. Import/Delete rows are inventoried, never touched. """ from hatch_menu import controls, dialog TAB = "Data controls" SWITCH_LABEL = "Help improve our AI models" _KEYWORDS = ("improv", "train", "model", "data", "usage") def _resolve(ws): """The improvement switch dict, or None when not resolvable.""" if not dialog.goto_tab(ws, TAB): return None switches = controls.list_switches(ws) for s in switches: blob = ((s.get("label") or "") + " " + (s.get("aria") or "")).lower() if SWITCH_LABEL.lower() in blob: return s if len(switches) == 1: return switches[0] for kw in _KEYWORDS: for s in switches: blob = ((s.get("label") or "") + " " + (s.get("aria") or "")).lower() if kw in blob: return s return None def ai_improvement(ws): """Improvement-switch state: True/False, None when unreadable.""" sw = _resolve(ws) return None if sw is None else bool(sw.get("checked")) def set_ai_improvement(ws, on): """Set the improvement switch; verify-then-fallback. Bool.""" sw = _resolve(ws) if sw is None: return False label = (sw.get("aria") or "").strip() \ or (sw.get("label") or "")[:40].strip() if not label: return False return controls.set_switch(ws, label, on) def describe(ws): """Inventory: switch state + row names (import/delete read-only).""" state = ai_improvement(ws) return {"ai_improvement": ("on" if state else "off") if state is not None else None, "rows": dialog.describe_rows(ws, TAB)}