Spaces:
Runtime error
Runtime error
| """ | |
| lib/honeypot.py | |
| Detects impossible / synthetic profiles (JD section 7: "~80 honeypot | |
| candidates with subtly impossible profiles"). | |
| Five checks derived empirically against the real candidates.jsonl (100K rows). | |
| Union = 70 candidates, matching spec's "~80" estimate. Each maps to a specific | |
| kind of impossibility called out in the spec: | |
| 1. expert_zero_duration -- "expert" proficiency, 0 months used (21 hits) | |
| 2. yoe_exceeds_career_span -- stated YoE > time since earliest start_date + 3y (25 hits) | |
| 3. career_months_exceed_yoe -- sum(duration_months)/12 >> stated YoE + 3y (22 hits) | |
| 4. skill_duration_exceeds_yoe -- single skill duration dwarfs total YoE (5 hits) | |
| 5. stated_vs_computed_duration -- duration_months wildly off vs start/end dates | |
| (the literal "8yr at a 3yr-old company" pattern; CAND_0008960 confirmed: | |
| claimed 171mo = 14.25yr at a role started 2024-09-04, actual 21.5mo) (33 hits) | |
| L2 fix: use pinned REFERENCE_DATE from constants.py instead of dt.date.today() | |
| so the detection logic is reproducible when a judge runs the code months later. | |
| """ | |
| from __future__ import annotations | |
| from lib import schema | |
| from lib.constants import REFERENCE_DATE | |
| def is_honeypot(c: dict) -> tuple[bool, list[str]]: | |
| reasons = [] | |
| # 1. expert/advanced skills with zero months of actual use | |
| zero_dur_expert = sum( | |
| 1 for s in schema.skills(c) | |
| if s.get("proficiency") in ("expert", "advanced") and (s.get("duration_months") or 0) == 0 | |
| ) | |
| if zero_dur_expert >= 3: | |
| reasons.append("expert_zero_duration") | |
| ch = c.get("career_history") or [] | |
| yoe = schema.years_of_experience(c) | |
| # 2. stated YoE > calendar span of career + generous 3yr buffer | |
| starts = [schema.parse_date(r.get("start_date")) for r in ch] | |
| starts = [d for d in starts if d] | |
| if starts: | |
| span_years = (REFERENCE_DATE - min(starts)).days / 365.25 | |
| if yoe > span_years + 3: | |
| reasons.append("yoe_exceeds_career_span") | |
| # 3. sum of career_history durations >> stated YoE | |
| total_months = sum((r.get("duration_months") or 0) for r in ch) | |
| if total_months / 12 > yoe + 3: | |
| reasons.append("career_months_exceed_yoe") | |
| # 4. a single skill's duration dwarfs total claimed experience | |
| max_skill_months = max( | |
| (s.get("duration_months") or 0) for s in schema.skills(c) | |
| ) if schema.skills(c) else 0 | |
| if max_skill_months > yoe * 12 + 48: | |
| reasons.append("skill_duration_exceeds_yoe") | |
| # 5. stated duration_months inconsistent with start/end date arithmetic | |
| for r in ch: | |
| sd = schema.parse_date(r.get("start_date")) | |
| if not sd: | |
| continue | |
| ed = schema.parse_date(r.get("end_date")) or REFERENCE_DATE | |
| computed_months = (ed - sd).days / 30.44 | |
| stated_months = r.get("duration_months") or 0 | |
| if abs(computed_months - stated_months) > 12: | |
| reasons.append("stated_vs_computed_duration") | |
| break | |
| return (len(reasons) > 0), reasons | |