-
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
fix(tailor): expand diff scope + preserve casing (#805); e2e-monitor JD-keyword tolerance #827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,7 +81,13 @@ def _check_for_truncation(data: dict[str, Any]) -> None: | |
| re.compile(r"^summary$"), | ||
| re.compile(r"^workExperience\[\d+\]\.description(\[\d+\])?$"), | ||
| re.compile(r"^personalProjects\[\d+\]\.description(\[\d+\])?$"), | ||
| # Education description is a single string (Education.description: str | None), | ||
| # so only the scalar path is allowed — not a [j]-indexed bullet form. | ||
| re.compile(r"^education\[\d+\]\.description$"), | ||
| re.compile(r"^additional\.technicalSkills$"), | ||
| re.compile(r"^additional\.languages$"), | ||
| re.compile(r"^additional\.certificationsTraining$"), | ||
| re.compile(r"^additional\.awards$"), | ||
| ] | ||
|
|
||
| # Blocked path prefixes — always rejected | ||
|
|
@@ -130,6 +136,10 @@ def _is_path_blocked(path: str) -> bool: | |
| return True | ||
|
|
||
| if path.startswith("education"): | ||
| # Education descriptions may be tailored; degree/institution/years stay | ||
| # blocked (they are also caught by the blocked-leaf-name check above). | ||
| if re.match(r"^education\[\d+\]\.description$", path): | ||
| return False | ||
| return True | ||
|
|
||
| return False | ||
|
|
@@ -1286,6 +1296,91 @@ def calculate_resume_diff( | |
| confidence="medium" | ||
| )) | ||
|
|
||
| # 4b. Compare education descriptions (a single string per entry, not a list) | ||
| original_education = original.get("education", []) | ||
| improved_education = improved.get("education", []) | ||
| for idx in range(max(len(original_education), len(improved_education))): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WARNING: Education descriptions are compared by array index. If an education entry is added or removed at a different position (e.g., a new entry prepended at index 0), descriptions will be compared against the wrong entries — |
||
| orig_entry = original_education[idx] if idx < len(original_education) else None | ||
| impr_entry = improved_education[idx] if idx < len(improved_education) else None | ||
| orig_desc = ( | ||
| str(orig_entry.get("description") or "").strip() | ||
| if isinstance(orig_entry, dict) | ||
| else "" | ||
| ) | ||
| impr_desc = ( | ||
| str(impr_entry.get("description") or "").strip() | ||
| if isinstance(impr_entry, dict) | ||
| else "" | ||
| ) | ||
| if orig_desc == impr_desc: | ||
| continue | ||
| if orig_desc and not impr_desc: | ||
| change_type = "removed" | ||
| elif impr_desc and not orig_desc: | ||
| change_type = "added" | ||
| else: | ||
| change_type = "modified" | ||
| changes.append(ResumeFieldDiff( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Education description edits are now emitted twice: once in the new Prompt for AI agents |
||
| field_path=f"education[{idx}].description", | ||
| field_type="education", | ||
| change_type=change_type, | ||
| original_value=orig_desc or None, | ||
| new_value=impr_desc or None, | ||
| confidence="medium", | ||
| )) | ||
|
|
||
| # 4c. Compare languages (order changes are intentionally ignored) | ||
| orig_langs = _build_string_index( | ||
| original.get("additional", {}).get("languages", []), | ||
| "additional.languages", | ||
| ) | ||
| new_langs = _build_string_index( | ||
| improved.get("additional", {}).get("languages", []), | ||
| "additional.languages", | ||
| ) | ||
| for lang_key in set(new_langs) - set(orig_langs): | ||
| changes.append(ResumeFieldDiff( | ||
| field_path="additional.languages", | ||
| field_type="language", | ||
| change_type="added", | ||
| new_value=new_langs[lang_key], | ||
| confidence="high", | ||
| )) | ||
| for lang_key in set(orig_langs) - set(new_langs): | ||
| changes.append(ResumeFieldDiff( | ||
| field_path="additional.languages", | ||
| field_type="language", | ||
| change_type="removed", | ||
| original_value=orig_langs[lang_key], | ||
| confidence="medium", | ||
| )) | ||
|
|
||
| # 4d. Compare awards (order changes are intentionally ignored) | ||
| orig_awards = _build_string_index( | ||
| original.get("additional", {}).get("awards", []), | ||
| "additional.awards", | ||
| ) | ||
| new_awards = _build_string_index( | ||
| improved.get("additional", {}).get("awards", []), | ||
| "additional.awards", | ||
| ) | ||
| for award_key in set(new_awards) - set(orig_awards): | ||
| changes.append(ResumeFieldDiff( | ||
| field_path="additional.awards", | ||
| field_type="award", | ||
| change_type="added", | ||
| new_value=new_awards[award_key], | ||
| confidence="high", | ||
| )) | ||
| for award_key in set(orig_awards) - set(new_awards): | ||
| changes.append(ResumeFieldDiff( | ||
| field_path="additional.awards", | ||
| field_type="award", | ||
| change_type="removed", | ||
| original_value=orig_awards[award_key], | ||
| confidence="medium", | ||
| )) | ||
|
|
||
| # 5. Compare added/removed/modified entries | ||
| # Descriptions are diffed separately; ignore them when detecting entry-level changes. | ||
| _append_entry_changes( | ||
|
|
@@ -1304,6 +1399,7 @@ def calculate_resume_diff( | |
| original.get("education", []), | ||
| improved.get("education", []), | ||
| _format_education_entry, | ||
| {"description"}, # diffed separately in step 4b — avoid duplicate entry-level diffs | ||
| ) | ||
| _append_entry_changes( | ||
| changes, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: These new list targets need path-specific action gating; as written, malformed diffs can append or replace values instead of only reordering them.
Prompt for AI agents