fix: doctor, search, and CV fixes found auditing real job offers - #56
Merged
Conversation
A newer DB schema than the installed applyr is forward-compatible, not breakage, but doctor never reported it at all — the only signal was a bare stderr line from init_db(), disconnected from the structured health-check report and easy to misread as an actual problem. Add a dedicated schema-version check to _check_database() that surfaces as a labeled "note" (not an "issue"), so it doesn't fail the exit code and reads clearly as informational. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…check search and add disagreed on what counts as "the same company": add's duplicate detection uses an exact, case-insensitive match (find_company_offers), while search used a broad LIKE substring across five fields. Following AGENT_INSTRUCTIONS.md Step 2's "check duplicates via search" as written could miss or over-match relative to what add actually blocks on. Add `search --company <name>` as an exact-match mode reusing find_company_offers, so the pre-add duplicate check now uses the same definition add enforces. Plain `search <keyword>` keeps its LIKE-based substring behavior — a fuzzy company match there risks false positives on short names, which is why this wasn't fixed by loosening search itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
review-blind's rubric scores the CV artifact (keywords, ATS format, evidence, clarity, length) — the same axes cv review uses — not whether the candidate fits the offer. That judgment already happens in Step 3 (add's Matcher topic scoring). Nothing in the workflow said this explicitly, so the ATS SCORE read like a second fit opinion when it isn't one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two independent fixes to the generated-CV pipeline: - _make_slug() dropped the job title from generated filenames — a CV used to be named cv-<company>-<title>.md (e.g. cv-acm-innovacion-y-personas-desarrollador.md), truncated to 40 chars in a way that made the file hard to identify at a glance. Filenames are now cv-<company>.md. A second offer at the same company (a normal case per duplicates.py — applying to multiple roles at one company is not a duplicate) gets an automatic id suffix instead of colliding with or silently overwriting the first CV; regenerating the SAME offer's CV still hits the existing already_exists/--force guard. - cv pdf never validated the "1 page (2 for 5+ years)" ATS rule that cv review already states in its rubric — generation always reported success regardless of length. Added a page count after generation (regex over raw PDF bytes, no new dependency — the project's stated philosophy is colorama as the only dependency) and a non-blocking warning when it exceeds the limit, derived from the offer's seniority_level (senior/lead/director allow 2 pages, else 1). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Found while auditing a real offer end-to-end: cv review-blind reads cv-master.md fresh, BEFORE any CV is generated or trimmed for the offer (Step 5 runs ahead of Step 6). It reused the same rubric as cv review (which evaluates an already-tailored CV file), including "ATS Format Compliance" and "Length & Relevance" (1-2 pages) — both criteria that only make sense against a finished document. A master profile spanning a full career history will always fail a page-count check it was never meant to pass yet, dragging the score down regardless of how strong the actual candidate material is. Split into a dedicated _BLIND_REVIEW_RUBRIC / _BLIND_REVIEW_OUTPUT_FORMAT that drops both finished-document criteria and reweights Keyword Match, Evidence & Metrics and Clarity & Impact to 100%. cmd_cv_review (which evaluates the tailored, generated CV) keeps the original rubric unchanged — that's the right place for the page-count and ATS-format checks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- test_doctor.py: the new schema-forward-compat test asserted both "note(s) to review" in out AND "note(s)" not in out — a contradiction that only passed by accident. Removed the wrong second assertion. - test_cv_review_blind.py: the fixture's compatibility_pct (45) coincidentally matched the new blind rubric's "Keyword Match (weight: 45%)" line, making the blindness check fail on an unrelated string collision. Changed the fixture to 47, a value that can't coincide with a round rubric weight. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Chain Context
Summary
This is PR 1 of 2 stacked PRs (chained via /chained-pr, split because the combined diff exceeded the 500-line budget). PR 2 (branch fix/cc-doctor-search-cv-fixes) is stacked on top of this one and depends on it.
Six commits, all bugs found by actually using applyr end-to-end against real job offers (registering offers, generating CVs, running review-blind) rather than by reading the code:
doctornever checked schema version at all; the only signal was a bare stderr line from init_db() on every OTHER command, disconnected from doctor's structured report. Added a proper "note" (not "issue") check to _check_database().search(LIKE substring) andadd's duplicate detection (exact match) disagreed on what counts as "the same company." Addedsearch --company <name>as an exact-match mode reusing the same find_company_offers() add already uses, and updated AGENT_INSTRUCTIONS.md Step 2 to use it.cv pdfgeneration (regex over raw PDF bytes, no new dependency) that warns when the ATS 1-2 page rule is exceeded.Verified locally: 561 tests pass on this branch (
python3 -m pytest -q).Verification
Checklist
fix/cc-workflow-audit-fixes)