feat: rewrite resume prose after scoring - #384
Conversation
Adds a --rewrite/--rewrite-score stage that rewrites editable resume prose (summary, work summary/highlights, project description/highlights) from the already-extracted JSONResume, using the role rubric and evaluation feedback. - rewriter.py: ResumeRewriter mirrors ResumeEvaluator (TemplateManager, LLM provider, JSON-schema structured output). Narrow per-section output schemas plus a deterministic _merge keep protected fields (name, contact, dates, URLs, education) byte-identical by construction; rewrites are id-keyed so a reordered response cannot misattribute content. Failed rewrites fall back to the original section. - prompts/templates/resume_rewrite.jinja + rewrite_system_message.jinja: per-section rewrite prompt with no-fabrication rules and BAD/GOOD examples. - scoring.py: compute_totals() as the single source of truth for report, CSV, and delta arithmetic. - score.py: --rewrite / --rewrite-score flags, --resume-json input mode, CSV rewrite_delta column, optional re-score with before/after delta. - models.py: RewrittenBasics/RewrittenWork/RewrittenProject (+list wrappers) with id echo for identity-keyed merge.
|
Only prose fields are rewritten — summary, work highlights/summaries, project descriptions/highlights. Things like name, dates, contact info, URLs, education, and skills are structurally impossible for the LLM to touch, because the output schema (RewrittenBasics, RewrittenWork, RewrittenProject) simply doesn't expose those fields. |
Summary
Closes #383 — after scoring, the pipeline can now rewrite the extracted resume's prose into stronger, rubric-aligned content and emit a revamped resume.
Problem / motivation
The pipeline previously ended at a scorecard: it told a candidate what was weak but produced no improved version of the resume. This PR adds a final stage that rewrites editable prose sections from the already-extracted, validated JSONResume (never the raw PDF), and writes the result to
resume_revamped_<basename>.json(+ Markdown).What changed
rewriter.py—ResumeRewritermirrorsResumeEvaluator(TemplateManager,initialize_llm_provider, JSON-schema structured output). It rewrites the basicssummary, worksummary/highlights, and projectdescription/highlights.RewrittenBasics/RewrittenWork/RewrittenProjectinmodels.py) only expose editable fields, and_mergerebuilds the resume from the original data applying only whitelisted edits — keyed by theideach entry echoes back, so a reordered LLM response cannot misattribute content. Protected fields (name, contact, dates, URLs, education, skills) cannot drift by construction.scoring.py—compute_totals()becomes the single source of truth for score arithmetic (report, CSV row, rewrite delta).score.py— new flags:--rewrite(rewrite + save) and--rewrite-score(also re-score and print a before/after delta); new--resume-json <path>input mode; CSV gains arewrite_deltacolumn.prompts/templates/resume_rewrite.jinja+rewrite_system_message.jinjawith no-fabrication rules.Prompt before/after examples
Summary section:
Work section:
Projects section:
These examples rephrase facts already present and never add new numbers or claims.
Notes