▌ NICK COMMAND BASE ▐
2026-06-07 04:34

▌ ResMyCV — ATS Optimisation Feature.md

▒ PATH: Projects/ResMyCV — ATS Optimisation Feature.md
▒ SIZE: 3.5 KB
▒ MODIFIED: 2026-06-02 03:12
← BACK TO VAULT
# ResMyCV — ATS Optimisation Feature **Date:** June 1, 2026 **Status:** Deployed to Railway (rezmycv.com) --- ## What was built Two-step CV creation flow replacing the previous single-step tailor: 1. **Step 1 — Tailor CV** (`/cv/tailor`) - Takes: profile CV + job description + gap answers - Generates: base tailored CV with summary, experience, skills, education 2. **Step 2 — Match ATS Keywords** (`/cv/optimise`) - Takes: tailored CV + job description + ATS keywords + requirements + gap answers from Supabase - Rewrites: all fields (personal, summary, experience, skills, education) for ATS keyword match - Draws from: profile CV, tailored CV, gap answers (3 sources) - Rule: summary MUST always be present — never null, never empty, never removed --- ## Key files changed | File | Change | |------|--------| | `services/optimise.py` | New — ATS optimisation service, all fields eligible, mandatory summary rule | | `services/cover_letter.py` | Added humanised sentence length mixing | | `app.py` | Added `/cv/optimise` route, passes gap_answers from Supabase user_cvs | | `templates/cv_editor.html` | Added purple "Match ATS Keywords" button + JS handler | | `templates/cv_editor.html` | Fixed nl2br → `replace('\n','<br>')\|safe` | | `templates/dashboard.html` | "Delete CV" → "Delete Profile CV", added how-it-works info box | | `templates/dashboard.html` | How-it-works box: one job at a time, download CV+CL then delete to start fresh | | `templates/cover_letter.html` | nl2br filter fix | --- ## ATS Optimise prompt rules - All fields eligible for rewriting (personal, summary, experience, skills, education) - Only factual core must stay truthful (real jobs, real dates, real titles) - Gap answers enrich experience bullets - **MANDATORY OUTPUT RULE:** summary must ALWAYS appear — 2-3 sentence first-person professional summary - Safeguard in code: if AI returns empty summary, restored from original CV before returning --- ## Cover letter humanisation Added to prompt: - Short punchy sentences (3-6 words) mixed with longer flowing ones (15-20 words) - Natural human rhythm — not uniform sentence length - Keep cover letter grounded in CV + gap answers facts --- ## Bug fixed: summary missing from optimised CV (June 1, 2026) **Symptom:** AI returned valid JSON with `summary` field, debug log confirmed it was present, but template showed no summary. **Root cause:** `_prepare_cv_context()` only copied summary into `personal` when `personal` was built from scratch (lines 51-60). When `personal` already existed from the AI output, the summary at top level was never copied over. **Fix (app.py line 65-71):** ```python if "personal" not in ctx: ctx["personal"] = {...} if ctx.get("summary"): ctx["personal"]["summary"] = ctx["summary"] else: # personal already exists from AI output — ensure summary is also present in it if ctx.get("summary") and not ctx["personal"].get("summary"): ctx["personal"]["summary"] = ctx["summary"] ``` **Debug added:** - `services/optimise.py`: print statements for raw response type, parsed keys, summary value, fallback restoration - `app.py /cv/optimise`: app.logger.info of returned keys and summary value --- ## Known issues fixed - `nl2br` Jinja2 filter didn't exist on Railway → replaced with `|replace('\n','<br>')|safe` - Summary missing from optimised CV → `_prepare_cv_context` now handles both cases (personal built from scratch AND personal already from AI output) --- ## GitHub Repo: `ncik8/TailorMyCV` Railway auto-deploys on push to main.
▒▒▒ READY CPU: 12% MEM: 4.2G NET: OK OBSIDIAN ▒ VIEWING