""" Simulate the WORST production case: LLM returns only 2 roles (drops BYJU's and ML Edutech), no recruiter pitch, 3 bullets per role. Verify the v4 backfill + pitch enforcement + weaving brings it to 90%+. """ import os, sys, io, shutil sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') src_pdf = r'C:\Users\Nxtwave\Desktop\resume\Saiteja_Tirunagari_Resume A 26 - Copy.pdf' dst_pdf = 'data/resume/resume.pdf' os.makedirs(os.path.dirname(dst_pdf), exist_ok=True) if not os.path.exists(dst_pdf): shutil.copyfile(src_pdf, dst_pdf) # Monkey-patch the LLM call to return a deliberately weak v4 response from src.resume_customizer import ResumeCustomizer, _read_docx_text from src.llm_client import LLMClient from src.ats_scorer import score_resume def make_weak_response(resume_dict, job_title, company): """Mimic worst-case LLM: 2 roles only, no pitch, 3 bullets each.""" return { "name": resume_dict["name"], "contact": resume_dict["contact"], # NO recruiter pitch — generic 2-sentence summary "summary": ( "Product Manager with 5+ years of experience driving product development " "in fast-paced startups. Built funnel optimization and AI-powered features " "that scaled to 140,000+ users with measurable business impact." ), "roles": [ # Only 2 of the 4 original roles — LLM dropped older ones { "title": resume_dict["roles"][0]["title"], "company": resume_dict["roles"][0]["company"], "location": resume_dict["roles"][0]["location"], "dates": resume_dict["roles"][0]["dates"], "bullets": [ "Led NIAT Application Portal revamp scaling to 141,269 verified leads", "Drove payment conversion lift of +35.87 percentage points", "Built AI chatbot generating 6,776 leads", ], }, { "title": resume_dict["roles"][1]["title"], "company": resume_dict["roles"][1]["company"], "location": resume_dict["roles"][1]["location"], "dates": resume_dict["roles"][1]["dates"], "bullets": [ "Managed 20 customer-success specialists covering 40,000 customers", "Maintained refund rate below 5% and satisfaction above 95%", ], }, ], "achievements": [ "Scaled to 141,269 verified leads", "Lifted payment conversion +35.87 pp", ], "education": resume_dict["education"], } # Patch LLMClient.tailor_resume_v4 to return our weak response _original_v4 = LLMClient.tailor_resume_v4 def _mocked_v4(self, cfg, resume_dict, jd_text, job_title, company, assessment): return make_weak_response(resume_dict, job_title, company) LLMClient.tailor_resume_v4 = _mocked_v4 from src.llm_client import LLMClient as LC rc = ResumeCustomizer.__new__(ResumeCustomizer) rc.llm = LC.__new__(LC) rc.resume_text = '' rc.output_dir = 'data/output/resumes/_v4_backfill_test' os.makedirs(rc.output_dir, exist_ok=True) rc.fast_model_cfg = {"model": "fake", "api_key": "fake", "base_url": "https://fake"} rc._pending_summary_inject = [] print('━' * 78) print(f'{"JD":<48} {"v4_only":>9} {"FinalATS":>9} {"Roles":>6} {"Words":>6}') print('━' * 78) jd_files = { 'airtel_pm': ('Product Manager', 'Airtel'), 'sumo_logic_pm': ('Product Manager', 'Sumo Logic'), 'edgeverve_pm': ('Product Manager', 'EdgeVerve'), 'aditya_birla_apm': ('Associate Product Manager', 'Aditya Birla Capital'), } for jd_file, (role_title, company) in jd_files.items(): with open(f'tests/fixtures/jds/{jd_file}.txt', encoding='utf-8') as f: jd = f.read() job = { "title": role_title, "company": company, "description": jd, "_raw_assessment": {"ats_keywords": []}, } filepath = os.path.join(rc.output_dir, f'{company.replace(" ", "_")}_{jd_file}.docx') # Call the actual v4 flow result = rc._generate_resume_v4(job, cfg=rc.fast_model_cfg, filepath=filepath) if not result: print(f'{(role_title + " @ " + company):<48} v4 FAILED') continue text = _read_docx_text(result) r = score_resume(text, jd) # Count roles + words in the actual generated DOCX from docx import Document doc = Document(result) role_lines = sum( 1 for p in doc.paragraphs if p.text and any(co in p.text for co in ["NxtWave", "Think & Learn", "ML Edutech", "BYJU"]) ) print(f'{(role_title + " @ " + company):<48} {"weak":>9} {r["ats_score"]:>8} {role_lines:>4} {r["word_count"]:>5}') print('━' * 78) print('\nThis test simulates the WORST case: LLM returns 2 roles only, no') print('pitch, 3 bullets each. v4 backfill + pitch enforcement + weaving') print('should still produce 90%+ resumes with all 4 candidate roles preserved.')