How CV and Cover Letter Claims Are Verified Against Multiple Sources in AI-Job-Search
The AI-Job-Search framework enforces a six-stage verification pipeline that cross-references every claim against internal candidate profiles, external company websites, and technical PDF standards to ensure factual accuracy before submission.
The MadsLorentzen/ai-job-search repository implements a rigorous, multi-layered verification architecture designed to eliminate hallucinated or inaccurate content from automated job applications. Every bullet point written to a CV or cover letter must survive internal grounding audits, external web research, and mechanical ATS validation before the final documents are compiled.
Internal Grounding: Anchoring Claims to Canonical Sources
The first line of defense occurs inside the apply command (.claude/commands/apply.md), which executes a "Grounding Audit" at line 92. This audit cross-checks every generated bullet point against three canonical internal sources to prevent data drift:
- The candidate profile (
.claude/skills/job-application-assistant/01-candidate-profile.md) - The master CV template (
cv/main_example.tex) - The candidate-profile section within
CLAUDE.md
The system reads these files and compares each claim, rejecting any bullet that does not match the user's own data exactly. As implemented in the repository, the grounding audit ensures dates, role titles, metrics, and technology names remain consistent with the verified candidate history.
def grounding_audit(cv_path, cover_path):
# Load canonical sources
profile = read_file(".claude/skills/job-application-assistant/01-candidate-profile.md")
master_cv = read_file("cv/main_example.tex")
claude_section = read_file("CLAUDE.md")
# Compare each generated bullet against the union of sources
for bullet in extract_bullets(cv_path):
if not bullet_in_sources(bullet, profile, master_cv, claude_section):
raise VerificationError(f"Unverified claim: {bullet}")
The function aborts the entire workflow if any generated bullet cannot be found unchanged in the three source files, preventing the LLM from inventing experience or altering historical metrics.
External Verification: Validating Company-Specific Facts
After internal grounding, the pipeline verifies company-specific statements (partnerships, product usage, expansions) using WebFetch and WebSearch. According to .claude/commands/apply.md lines 124-131, the search initiates from the official company domain and never from URLs embedded within the job posting text, which are treated as untrusted.
The workflow fetches pages, follows links, and extracts relevant snippets. A claim is only retained if the fetched page independently confirms it; otherwise, the bullet is dropped or edited.
def verify_company_claim(claim, company_name):
# Start search from the official domain
results = websearch(f"{company_name} official site")
for url in results:
page = webfetch(url, headers={"User-Agent": "ai-job-search-bot"})
if claim in page.text:
return True
return False
Only claims appearing on pages fetched directly from the company's verified website are accepted into the final documents.
Technical Validation: Ensuring ATS Compatibility
The compiled PDFs undergo mechanical verification via tools/verify_pdf.py. This script extracts the PDF's text layer—first attempting pypdf, then falling back to pdftotext (Poppler)—to verify ATS readability.
python tools/verify_pdf.py cv/main_acme_corp_software_engineer.pdf \
--dump-text cv/main_acme_corp_software_engineer.txt
The script validates page count, extractable text presence, and character encoding integrity. It reports parsing failures, missing text layers, or non-ASCII replacement characters that could cause Applicant Tracking Systems to reject the document.
Keyword Coverage and Final Quality Assurance
Following text extraction, the CV is scored against the job posting's keywords. As described in the repository documentation around line 247, only keywords genuinely present in the candidate's profile are added; gaps remain visible to avoid "keyword stuffing" that could trigger ATS spam filters.
The final verification stages include:
-
Visual Audit: The apply command (lines 213-218 in
.claude/commands/apply.md) explicitly requires compiling both documents and visually verifying layout consistency, page breaks, and content placement before submission. -
Checklist Reporting: A pass/fail checklist defined in
CLAUDE.md(lines 106-112) summarizes which verification items succeeded, printing results to the console and archiving them with the application.
Summary
- Internal grounding cross-references every claim against three canonical source files to prevent data drift.
- External verification uses web search and fetch operations starting from official company domains to validate facts.
- PDF technical validation extracts text layers using
verify_pdf.pyto ensure ATS readability. - Keyword scoring matches extracted content against job requirements without stuffing.
- Visual and checklist audits provide final human-in-the-loop verification before submission.
Frequently Asked Questions
What are the three canonical sources used in the grounding audit?
The grounding audit compares generated content against the candidate profile at .claude/skills/job-application-assistant/01-candidate-profile.md, the master CV template at cv/main_example.tex, and the candidate-profile section within CLAUDE.md. This ensures all dates, metrics, and technologies match the user's verified history.
How does the framework prevent false claims about target companies?
Company-specific statements are verified using WebFetch and WebSearch starting exclusively from the official company domain, ignoring URLs found in the job posting text. A claim is only accepted if an independently fetched page from the company's website confirms the fact.
What happens if the PDF fails technical validation?
The tools/verify_pdf.py script reports parsing failures, missing text layers, or encoding errors. The workflow halts until the PDF generation is corrected, ensuring that only ATS-readable documents with properly extractable text layers are submitted.
Can the verification pipeline be run manually for individual documents?
Yes. While the /apply command orchestrates the full pipeline, individual components like the PDF validator can be executed standalone using the command-line interface: python tools/verify_pdf.py <pdf_path> --dump-text <output.txt>.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →