license: agpl-3.0 language:
A CV/job-post fit-scoring benchmark: 250 synthetic CVs, 404 job postings and 5,000 CV/job pairs, each judged on 17 questions with a score and a confidence. It trains and evaluates jobfit-model, a Jev-like typed-decision model (a state plus typed questions in, one typed answer per question id out).
questions.json # the 17 questions: type, name, scope, question text, 5 criteria
cvs/*.md # synthetic CVs, plain markdown
jobs/<company>/*.md # job postings, markdown with YAML frontmatter
labels/ # LLM-judge labels, one JSON object per line
splits/ # which pairs belong to train / val / test / calib
cvs/<name>.md: a synthetic CV.
jobs/<company>/<posted_at>-<slug>.md: a job posting. Frontmatter keys: company, title, location, url (source page), posted_at.
questions.json: an object keyed by question id. Each entry has type (score), name, scope (pairwise, cv or job), question and criteria (5 level descriptions). Scores are on a 0–1 scale; the 5 levels map to 0, 0.25, 0.5, 0.75, 1.
| scope | question ids |
|---|---|
| pairwise (13) | skills_match, experience_level_match, domain_industry_relevance, education_qualifications_match, seniority_role_level_fit, career_trajectory_fit, responsibilities_overlap, location_work_arrangement_fit, soft_skills_match, recency_of_relevant_experience, overall_fit, interview_readiness, culture_company_alignment |
| cv (2) | cv_clarity_structure_quality, cv_likely_llm_generated |
| job (2) | job_post_clarity_structure_quality, job_post_likely_llm_generated |
labels/pairs.jsonl (5,000 rows): cv, job (paths relative to the corpus root), then <id>_score and <id>_confidence for each of the 13 pairwise ids, and labeling_method. Confidence is the judge's 0–1 certainty in its score.
labels/cvs.jsonl (250 rows): cv, then _score / _confidence for the 2 cv ids.
labels/jobs.jsonl (404 rows): job, then _score / _confidence for the 2 job ids.
labels/*_double.jsonl: a second, independent rating of a subset (300 pairs, 25 CVs, 87 jobs), same columns as the files above. Use them to measure inter-rater agreement.
splits/{train,val,test,calib}.jsonl (3,500 / 500 / 500 / 500 rows): {cv, job} keys only. Join on (cv, job) with labels/pairs.jsonl to get labels:
from datasets import load_dataset
root = "hf://datasets/gw0/jobfit-jevbench"
pairs = load_dataset("json", data_files=f"{root}/labels/pairs.jsonl", split="train").to_pandas()
test = load_dataset("json", data_files=f"{root}/splits/test.jsonl", split="train").to_pandas()
test = test.merge(pairs, on=["cv", "job"])
test is fully held out (its CVs appear nowhere else). train, val and calib are CV-disjoint from each other; jobs are shared across all four.claude-sonnet-5. The *_double files come from the second rater claude-opus-5-5. labeling_method records the rater per row.*_likely_llm_generated is a model's estimate, not ground truth.Job fetching (data/fetch_jobs/), CV generation, labelling and PII scrubbing (data/pii_scrub.py) live in jobfit-model.
*_double for rater noise.test has only 25 distinct CVs, so per-CV statistics are noisy; bootstrap over CVs.The dataset is for non-commercial ML research and demo use. Per-source review of public robots.txt and terms of service (2026-10-09) (engineering-level, not a legal opinion).
| Source (posts) | robots.txt | Terms |
|---|---|---|
| Ashby (236) | disallows /meeting/, /b/, /api/, none fetched | customer terms bind Ashby's customers; nothing found on readers of public pages |
| Greenhouse (116) | no active rules on job pages | agreement unreachable; no anti-scraping clause found |
| Workday (40) | careers sites allowed; only /refreshFacet/ and internal sites disallowed | no public terms found; employer policy applies |
| Lever (12) | Allow: /, Crawl-delay: 1 | ToS page unreachable; no clause found |
/wday/cxs/ JSON endpoints, which robots.txt does not name.Copyright © 2026 gw0 [email protected]. Licensed under AGPL-3.0-or-later.
CVs are synthetic. Job posts come from public Greenhouse, Lever, Ashby and Workday pages, keep their source url, and remain under their publishers' rights and licenses. Not a legal opinion.
If my work saves you time, money, or tokens, consider sponsoring the work that keeps it maintained — and tell whoever else benefits, human or agent.
license: agpl-3.0 language:
A CV/job-post fit-scoring benchmark: 250 synthetic CVs, 404 job postings and 5,000 CV/job pairs, each judged on 17 questions with a score and a confidence. It trains and evaluates jobfit-model, a Jev-like typed-decision model (a state plus typed questions in, one typed answer per question id out).
questions.json # the 17 questions: type, name, scope, question text, 5 criteria
cvs/*.md # synthetic CVs, plain markdown
jobs/<company>/*.md # job postings, markdown with YAML frontmatter
labels/ # LLM-judge labels, one JSON object per line
splits/ # which pairs belong to train / val / test / calib
cvs/<name>.md: a synthetic CV.
jobs/<company>/<posted_at>-<slug>.md: a job posting. Frontmatter keys: company, title, location, url (source page), posted_at.
questions.json: an object keyed by question id. Each entry has type (score), name, scope (pairwise, cv or job), question and criteria (5 level descriptions). Scores are on a 0–1 scale; the 5 levels map to 0, 0.25, 0.5, 0.75, 1.
| scope | question ids |
|---|---|
| pairwise (13) | skills_match, experience_level_match, domain_industry_relevance, education_qualifications_match, seniority_role_level_fit, career_trajectory_fit, responsibilities_overlap, location_work_arrangement_fit, soft_skills_match, recency_of_relevant_experience, overall_fit, interview_readiness, culture_company_alignment |
| cv (2) | cv_clarity_structure_quality, cv_likely_llm_generated |
| job (2) | job_post_clarity_structure_quality, job_post_likely_llm_generated |
labels/pairs.jsonl (5,000 rows): cv, job (paths relative to the corpus root), then <id>_score and <id>_confidence for each of the 13 pairwise ids, and labeling_method. Confidence is the judge's 0–1 certainty in its score.
labels/cvs.jsonl (250 rows): cv, then _score / _confidence for the 2 cv ids.
labels/jobs.jsonl (404 rows): job, then _score / _confidence for the 2 job ids.
labels/*_double.jsonl: a second, independent rating of a subset (300 pairs, 25 CVs, 87 jobs), same columns as the files above. Use them to measure inter-rater agreement.
splits/{train,val,test,calib}.jsonl (3,500 / 500 / 500 / 500 rows): {cv, job} keys only. Join on (cv, job) with labels/pairs.jsonl to get labels:
from datasets import load_dataset
root = "hf://datasets/gw0/jobfit-jevbench"
pairs = load_dataset("json", data_files=f"{root}/labels/pairs.jsonl", split="train").to_pandas()
test = load_dataset("json", data_files=f"{root}/splits/test.jsonl", split="train").to_pandas()
test = test.merge(pairs, on=["cv", "job"])
test is fully held out (its CVs appear nowhere else). train, val and calib are CV-disjoint from each other; jobs are shared across all four.claude-sonnet-5. The *_double files come from the second rater claude-opus-5-5. labeling_method records the rater per row.*_likely_llm_generated is a model's estimate, not ground truth.Job fetching (data/fetch_jobs/), CV generation, labelling and PII scrubbing (data/pii_scrub.py) live in jobfit-model.
*_double for rater noise.test has only 25 distinct CVs, so per-CV statistics are noisy; bootstrap over CVs.The dataset is for non-commercial ML research and demo use. Per-source review of public robots.txt and terms of service (2026-10-09) (engineering-level, not a legal opinion).
| Source (posts) | robots.txt | Terms |
|---|---|---|
| Ashby (236) | disallows /meeting/, /b/, /api/, none fetched | customer terms bind Ashby's customers; nothing found on readers of public pages |
| Greenhouse (116) | no active rules on job pages | agreement unreachable; no anti-scraping clause found |
| Workday (40) | careers sites allowed; only /refreshFacet/ and internal sites disallowed | no public terms found; employer policy applies |
| Lever (12) | Allow: /, Crawl-delay: 1 | ToS page unreachable; no clause found |
/wday/cxs/ JSON endpoints, which robots.txt does not name.Copyright © 2026 gw0 [email protected]. Licensed under AGPL-3.0-or-later.
CVs are synthetic. Job posts come from public Greenhouse, Lever, Ashby and Workday pages, keep their source url, and remain under their publishers' rights and licenses. Not a legal opinion.
If my work saves you time, money, or tokens, consider sponsoring the work that keeps it maintained — and tell whoever else benefits, human or agent.