mz_chatbot / scripts /check_lead_quality.py
Shurem's picture
initial commit
ff3c2e9
Raw History Blame Contribute Delete
5.78 kB
"""
check_lead_quality.py — guards the anti-fabrication rules.
Every check here exists because the code once did the opposite and shipped
invented contact data to the CRM. They are pure-logic assertions: no network, no
database, no API keys, so this runs anywhere and is safe to run repeatedly.
uv run python scripts/check_lead_quality.py
Exit code 0 means every guard holds. Non-zero prints which one broke.
The functions under test are extracted with `ast` and exec'd in isolation rather
than imported, so this works without google-genai / requests / ddgs installed and
covers BOTH copies — the root Streamlit module and the backend port, which must
not drift apart.
"""
from __future__ import annotations
import ast
import io
import re
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
AGENT_CORE = [
REPO_ROOT / "agent_core.py",
REPO_ROOT / "outreach-backend" / "app" / "services" / "agent_core.py",
]
LEAD_ENGINE = [
REPO_ROOT / "lead_engine.py",
REPO_ROOT / "outreach-backend" / "app" / "services" / "lead_engine.py",
]
WANT_FN = {"_distinctive_tokens", "_is_non_personal", "site_matches_lead"}
WANT_CONST = {"_NON_PERSONAL", "_COMPANY_STOPWORDS", "INDUSTRY_KEYWORDS"}
def _extract(path: Path) -> dict:
"""Pull the pure helpers out of a module without importing its dependencies."""
tree = ast.parse(io.open(path, encoding="utf-8").read())
keep: list = []
for node in tree.body:
if isinstance(node, ast.FunctionDef) and node.name in WANT_FN:
keep.append(node)
elif isinstance(node, ast.Assign):
if any(isinstance(t, ast.Name) and t.id in WANT_CONST for t in node.targets):
keep.append(node)
ns: dict = {"re": re}
mod = ast.Module(body=keep, type_ignores=[])
exec(compile(ast.fix_missing_locations(mod), str(path), "exec"), ns) # noqa: S102
return ns
class Checker:
def __init__(self) -> None:
self.failures = 0
def check(self, label: str, got, expect) -> None:
ok = got == expect
if not ok:
self.failures += 1
print(f" [{'ok ' if ok else 'FAIL'}] {label}: {got!r}" + ("" if ok else f" (expected {expect!r})"))
def absent(self, label: str, path: Path, needle: str) -> None:
# Comments are allowed to name the old bug; code is not.
hits = [
f"{path.name}:{i}"
for i, line in enumerate(io.open(path, encoding="utf-8"), 1)
if needle in line and not line.lstrip().startswith("#")
]
ok = not hits
if not ok:
self.failures += 1
print(f" [{'ok ' if ok else 'FAIL'}] {label}" + ("" if ok else f" -> found at {', '.join(hits)}"))
def main() -> int:
c = Checker()
for path in AGENT_CORE:
print(f"\n===== {path.relative_to(REPO_ROOT)} =====")
ns = _extract(path)
nonpersonal = ns["_is_non_personal"]
verdict = ns["site_matches_lead"]
# --- placeholder contacts must not reach a metered API ------------------
# The old test was `name.lower() in _NON_PERSONAL`, an equality check, so
# only a bare "Team" was caught. _NON_PERSONAL also carries a trailing ""
# entry, which a naive substring rewrite turns into "matches everything".
for name in ("Team", "Custom Sales Team", "Sales Desk", "Decision Maker", "unknown", ""):
c.check(f"_is_non_personal({name!r})", nonpersonal(name), True)
for name in ("Hal Garrett", "Jonathan Ward", "Maria Lopez"):
c.check(f"_is_non_personal({name!r})", nonpersonal(name), False)
# --- every standard category needs INDUSTRY_KEYWORDS -------------------
# A category with no entry got [] from .get() and fell straight through
# to "mismatch" whenever the company's name tokens missed.
missing = [k for k in ns["INDUSTRY_KEYWORDS"] if not ns["INDUSTRY_KEYWORDS"][k]]
c.check("no empty INDUSTRY_KEYWORDS entry", missing, [])
c.check(
"tech category can match",
verdict(
"Nordic Widget Labs",
"⚡ Tech & Commercial Products",
"We are a custom product manufacturer building bespoke industrial equipment.",
)[0],
"match",
)
# --- the two verdict invariants ----------------------------------------
c.check(
"blocked beats mismatch",
verdict("Acme", "⛳ Custom Golf Carts", "totally unrelated text here ok", blocked=True)[0],
"blocked",
)
c.check(
"real mismatch still caught",
verdict(
"Papilio Bespoke Kitchens",
"\U0001f6cb️ Luxury Furniture & Interiors",
"Read the latest novels and browse our paperback catalogue today.",
)[0],
"mismatch",
)
# --- no invented email, no manufactured URL ----------------------------
c.absent("no info@{domain} fabrication", path, 'f"info@{domain}"')
c.absent("no manufactured www..com fallback", path, 'f"https://www.{extract_domain')
c.absent("no hardcoded verified_direct on an empty phone", path, '"phone_status": "verified_direct"')
c.absent("no hardcoded verified_direct kwarg", path, 'phone_status="verified_direct",')
for path in LEAD_ENGINE:
print(f"\n===== {path.relative_to(REPO_ROOT)} =====")
c.absent("no Apollo contact@ fabrication", path, "contact@{org.get")
print()
if c.failures:
print(f"FAILED — {c.failures} guard(s) broken")
return 1
print("All lead-quality guards hold.")
return 0
if __name__ == "__main__":
sys.exit(main())