"""Candidate rewrite guards for the Builder light optimization (截图1/截图2 回归).""" from __future__ import annotations from typing import Any from app.builder_conversation import _candidate_rewrite class _StaticExpander: def __init__(self, optimized: str) -> None: self.optimized = optimized def expand(self, entry: dict[str, Any], *, context: dict[str, Any]) -> dict[str, Any]: return {"optimized_description": self.optimized, "source": "test"} class _Agent: def __init__(self, optimized: str) -> None: self.expander = _StaticExpander(optimized) def test_candidate_rewrite_does_not_inject_identity_into_education_description() -> None: """Identity fields have their own card slots; never merge them into the narrative (截图2).""" proposal = _candidate_rewrite( _Agent("在学校中学习数据结构、计算机视觉等课程。"), {"job_type": "campus"}, { "school": "东莞城市学院", "major": "软件工程", "degree": "本科", "description": "在学校中学习数据结构、计算机视觉等课程。", }, "education", ) assert proposal["optimized_description"] == "在学校中学习数据结构、计算机视觉等课程。" assert "东莞城市学院" not in proposal["optimized_description"] def test_candidate_rewrite_reports_uncovered_facts_without_appending() -> None: """Uncovered user facts are reported, not stitched onto the candidate (截图1 关键词尾巴).""" proposal = _candidate_rewrite( _Agent("完成数据库课程项目并参与实验室实践。"), {"job_type": "campus", "target_position": "backend engineer"}, {"description": "完成数据库课程项目。GPA: 4.3/5.0,排名前百分之10。"}, "education", ) assert proposal["optimized_description"] == "完成数据库课程项目并参与实验室实践。" assert proposal["uncovered_facts"] == ["GPA: 4.3/5.0", "排名前百分之10"] def test_candidate_rewrite_reports_other_uncovered_user_facts() -> None: original = ( "完成数据库课程项目,使用 Python 和 SQL 实现信息查询。" "获得校级一等奖学金,服务 300 名学生。" ) proposal = _candidate_rewrite( _Agent("参与学习与实践活动。"), {"job_type": "campus"}, {"description": original}, "education", ) assert proposal["optimized_description"] == "参与学习与实践活动。" for fact in ("完成数据库课程项目", "Python", "SQL", "获得校级一等奖学金", "服务 300 名学生"): assert fact in proposal["uncovered_facts"] def test_candidate_rewrite_reports_no_uncovered_facts_when_candidate_covers_all() -> None: proposal = _candidate_rewrite( _Agent("完成数据库课程项目。GPA: 4.3/5.0。"), {"job_type": "campus"}, {"description": "完成数据库课程项目。GPA: 4.3/5.0。"}, "education", ) assert proposal["uncovered_facts"] == [] def test_candidate_rewrite_reports_dropped_function_modules() -> None: """功能模块/平台简介被吞时必须进入未覆盖报告(只保留技术栈不算覆盖)。""" original = ( "全栈 AI 求职助手平台,包含 5 大功能模块:\n" "1. AI 对话式简历生成助手\n" "2. 简历导入 (PDF/DOCX 智能解析)\n" "技术栈: Next.js + React" ) proposal = _candidate_rewrite( _Agent("• 前端采用 Next.js 与 React 实现响应式界面。"), {"job_type": "campus"}, {"description": original}, "project_experience", ) assert any("AI 对话式简历生成助手" in fact for fact in proposal["uncovered_facts"]) assert any("简历导入" in fact for fact in proposal["uncovered_facts"]) assert not any("Next.js" in fact for fact in proposal["uncovered_facts"]) def test_candidate_rewrite_tolerates_covered_fragments_without_false_positives() -> None: original = "1. AI 对话式简历生成助手\n2. 简历导入智能解析" proposal = _candidate_rewrite( _Agent("负责 AI 对话式简历生成助手与简历导入智能解析两大模块。"), {"job_type": "campus"}, {"description": original}, "project_experience", ) assert proposal["uncovered_facts"] == []