Spaces:
Sleeping
Sleeping
| """ | |
| Deterministic verification for the LaTeX resume flow (src/latex_resume.py). | |
| Proves, without any LLM or LaTeX engine: | |
| 1. LaTeX → text extraction recovers the resume's words. | |
| 2. Honestly-includable JD keywords (PM/AI/SaaS craft) get injected into the | |
| LaTeX and therefore appear in the extracted text. | |
| 3. BLOCKED / fabrication-risk terms (certifications, seniority, employers, | |
| specialised engineering) are NEVER injected in ANY placement. | |
| 4. External-style coverage rises sharply after injection. | |
| 5. Keywords are DISTRIBUTED, not dumped: a Summary sentence, woven experience | |
| \\item clauses, and at most ONE compact competencies line — and re-running | |
| does not stack fragments (idempotent). | |
| Run: python scripts/verify_latex_resume.py | |
| """ | |
| import os | |
| import re | |
| import sys | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from src.latex_resume import ( | |
| latex_to_text, inject_keywords, optimize_latex_resume, | |
| _INJECT_MARKER, _INJECT_END, _INJECT_WEAVE, | |
| ) | |
| from src.external_ats import extract_external_keywords, external_coverage | |
| SAMPLE_LATEX = r""" | |
| \documentclass[11pt]{article} | |
| \usepackage[margin=0.75in]{geometry} | |
| \begin{document} | |
| \textbf{Jane Doe} \\ | |
| Product Manager | |
| \section*{Summary} | |
| Product manager who ships data-informed features and works with engineering and | |
| design to deliver customer value. Owned the product roadmap for a consumer app. | |
| \section*{Experience} | |
| \textbf{Product Manager, Acme} \\ | |
| \begin{itemize} | |
| \item Led discovery and defined the product backlog for a B2B dashboard. | |
| \item Ran A/B tests and shipped onboarding improvements that lifted activation. | |
| \end{itemize} | |
| \section*{Education} | |
| B.Tech, Computer Science | |
| \end{document} | |
| """ | |
| # A JD full of normal PM/Product/AI/SaaS vocabulary + a few fabrication-risk terms. | |
| SAMPLE_JD = """ | |
| We are hiring a Senior AI Product Manager. You will own product strategy and the | |
| product roadmap, drive stakeholder management, and partner with engineering on | |
| machine learning and generative AI features. Strong skills in product analytics, | |
| experimentation, A/B testing, go-to-market, user research, and agile delivery. | |
| SaaS and B2B experience preferred. Must have a CISSP certification, a PMP, and | |
| 12+ years of experience. Hands-on Kubernetes and CUDA kernel programming required. | |
| """ | |
| # Terms we must NEVER fabricate even though they appear in the JD. | |
| MUST_NOT_INJECT = ["cissp", "pmp", "12+ years", "cuda"] | |
| def main() -> int: | |
| print("=" * 70) | |
| print("LaTeX resume flow verification") | |
| print("=" * 70) | |
| # 1. Text extraction recovers resume words. | |
| base_text = latex_to_text(SAMPLE_LATEX) | |
| low = base_text.lower() | |
| assert "product manager" in low, "extraction lost 'product manager'" | |
| assert "backlog" in low, "extraction lost 'backlog'" | |
| assert "\\section" not in base_text, "extraction left raw LaTeX commands" | |
| print(f"[1] LaTeX-to-text OK ({len(base_text)} chars, no raw commands)") | |
| # 2/3/4. Full optimize in Maximum ATS Mode (no compile — text path only). | |
| report = optimize_latex_resume( | |
| SAMPLE_LATEX, SAMPLE_JD, | |
| maximum_ats_mode=True, | |
| compile_pdf=False, | |
| ) | |
| injected = [t.lower() for t in report["injected"]] | |
| expected = report["expected_terms"] | |
| before = external_coverage(expected, latex_to_text(SAMPLE_LATEX)) | |
| after_pct = report["pct"] | |
| print(f"[2] expected terms: {len(expected)} | injected: {len(injected)}") | |
| print(f" coverage before: {before['pct']}% -> after: {after_pct}%") | |
| # Some craft terms that should be safely injected (present in JD, low risk). | |
| want_some = [t for t in ("product strategy", "product roadmap", | |
| "stakeholder management", "generative ai", | |
| "machine learning", "a/b testing", "go-to-market", | |
| "user research", "saas", "b2b") | |
| if t in [e.lower() for e in expected]] | |
| injected_or_present = set(injected) | {p.lower() for p in report["present"]} | |
| covered_craft = [t for t in want_some if t in injected_or_present] | |
| assert len(covered_craft) >= 5, ( | |
| f"expected >=5 craft terms covered, got {covered_craft}") | |
| print(f"[3] craft terms covered ({len(covered_craft)}): {covered_craft}") | |
| # 3. No fabrication-risk term was injected in ANY placement (summary | |
| # sentence, woven \item clauses, or the competencies line). | |
| tex = report["tex"] | |
| frags = _injected_fragments(tex) | |
| bad = [t for t in MUST_NOT_INJECT if t in injected or t in frags] | |
| assert not bad, f"FABRICATION: injected blocked terms {bad}" | |
| print(f"[4] no fabrication: blocked terms absent from EVERY injected " | |
| f"placement ({MUST_NOT_INJECT})") | |
| # 4. Coverage improved meaningfully. | |
| assert after_pct >= before["pct"], "coverage did not improve" | |
| assert after_pct >= 70, f"coverage only {after_pct}% (expected >=70%)" | |
| print(f"[5] coverage improved {before['pct']}% -> {after_pct}% (>=70 target)") | |
| # 5. Distribution: at most one competencies line, a Summary sentence, and | |
| # woven experience / multi-section placement (no single dump block). | |
| comp_lines = tex.count(r"\textbf{Core Competencies:}") | |
| assert comp_lines <= 1, f"expected <=1 competencies line, got {comp_lines}" | |
| assert "Core focus areas include" in tex, ( | |
| "no Summary placement sentence (SAMPLE_LATEX has \\section*{Summary})") | |
| woven = ("(applying" in tex) and (_INJECT_WEAVE in tex) | |
| added_sections = {k["section"] for k in report["keywords"] | |
| if k["found_in_export"] and k["section"].endswith("(added)")} | |
| multi_section = any(s in ("Summary (added)", "Experience (added)") | |
| for s in added_sections) | |
| assert woven or multi_section, ( | |
| f"no distributed placement detected (sections={sorted(added_sections)})") | |
| print(f"[6] distribution OK: {comp_lines} competencies line, Summary sentence " | |
| f"present, woven={woven}, sections={sorted(added_sections)}") | |
| # 6. Structure + idempotency: balanced document, and re-running injection | |
| # reproduces the same fragments rather than stacking them. | |
| assert tex.count(r"\end{document}") == 1, "broken document env" | |
| again, _ = inject_keywords(tex, report["injected"]) | |
| assert again.count("Core focus areas include") == \ | |
| tex.count("Core focus areas include"), "summary not idempotent" | |
| assert again.count(r"\textbf{Core Competencies:}") == comp_lines, \ | |
| "competencies line not idempotent" | |
| assert again.count(_INJECT_WEAVE) == tex.count(_INJECT_WEAVE), \ | |
| "woven clauses not idempotent" | |
| assert again.count(_INJECT_MARKER) == tex.count(_INJECT_MARKER), \ | |
| "marker fragments not idempotent" | |
| print("[7] structure OK: balanced document, fragments stable on re-run " | |
| "(idempotent)") | |
| print("=" * 70) | |
| print("PASS — LaTeX flow DISTRIBUTES honest keywords (summary + experience +") | |
| print(f" one competencies line), blocks fabrication, coverage {after_pct}%.") | |
| print("=" * 70) | |
| return 0 | |
| def _injected_fragments(tex: str) -> str: | |
| """Concatenate the lowercased text of every injected fragment: the fenced | |
| blocks (summary sentence + competencies line) AND inline woven clauses.""" | |
| low = tex.lower() | |
| parts = [] | |
| block_pat = re.escape(_INJECT_MARKER.lower()) + r".*?" + \ | |
| re.escape(_INJECT_END.lower()) | |
| parts += re.findall(block_pat, low, flags=re.DOTALL) | |
| weave_pat = r" \(applying [^\n]*?\)" + re.escape(_INJECT_WEAVE.lower()) | |
| parts += re.findall(weave_pat, low) | |
| return " ".join(parts) | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |