Build CVMatchScore

KINDAreplaces $4.08/mosaves $48.96/yrback to the verdict

0%0 of 17 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A comparison tool that maps a job description's stated requirements against evidence in a CV, quoting both sides, and refuses to produce an overall score because there is nothing real for a score to measure.

estimated effort weekendthe files for this build are in the project pack

ParsingStructured extraction from both documents with positions keptRequirementsExtracted from the posting as discrete, quoted itemsEvidenceMatched to spans in the CV, or explicitly absentRefusalNo aggregate score anywhere in the model or interfaceRuntimeTypeScript with a local application

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the local application.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. installfree

    Why Designed CV templates are two-column and a naive extractor produces interleaved text that every later step then operates on.

    Get it A library exposing text with positions and block structure.

    Verify A two-column CV extracts in correct reading order

  3. installfree, needs memory

    Why A CV and the jobs someone is applying for are private in ways people underestimate, and this runs over both.

    Get it Any local runner with a model that returns structured output reliably. open ↗

    Verify Ten extractions return valid structured output with positions

  4. have readyfree

    Why Requirement extraction quality is only assessable against real postings, which vary from precise lists to three paragraphs of aspiration.

    Get it Collect postings you would actually apply for, including a vague one and one heavy with boilerplate.

    Verify Ten postings exist including one vague and one boilerplate-heavy

  5. decidefree

    Why The whole build refuses to predict, and the wording of that refusal is the most important text in the interface.

    Get it Write the sentence the report leads with about what the comparison does and does not tell them.

    Verify A written sentence exists and appears where the reader will see it

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- documents(id, kind, text, filename, added_at) · kind is cv or posting
- requirements(id, posting_id, quote, char_start, char_end, category, is_essential) · essential where the posting says so, never inferred
- evidence(requirement_id, cv_id, quote, char_start, char_end, strength, note)
- gaps(requirement_id, cv_id, kind, note) · kind is absent, weak or unclear
- rewrites(id, cv_id, requirement_id, suggestion, accepted_at) · suggestions, never applied automatically
- sessions(id, cv_id, posting_id, compared_at)
- There is deliberately no score column anywhere, because a stored number would be displayed and it would be invented.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DB_PATHrequired~/.local/share/cvmatch/data.dbYour CV and the jobs you are applying for. Personal in both directions.
EXTRACTION_MODELrequiredlocalRuns over your CV and your job search. Local is the sensible default.
EMIT_SCORErequiredneverPresent as a constant so the answer is visible. There is nothing real to score.
GENERATE_CV_TEXTrequiredneverPresent as a constant. A pasted claim becomes a lie at interview.
ALLOW_NETWORKrequiredneverPresent as a constant. Neither document needs to leave the machine.

The build, in order

  1. Reading both documents properly

    A CV and a posting parse into text with positions preserved.

    1. Designed CV templates are two-column and scramble under naive extraction.

      Files src/extract.ts

    2. Every claim later has to quote, which needs positions.

      Files src/documents.ts

    3. Partial text produces a comparison that is confidently wrong.

      Files src/extract.ts

    done when · tick each as it passes
    watch out
    • A CV in two columns, which is common in designed templates, extracts as interleaved nonsense with a naive reader, and every comparison after that operates on scrambled text while looking entirely plausible. Reconstruct reading order and check the output is readable before doing anything with it.
  2. Requirements as sentences, not keywords

    The posting yields discrete requirements you could argue with.

    1. A keyword loses what was actually being asked for.

      Files src/requirements.ts

    2. Inferring which are essential is guessing at someone else's priorities.

      Files src/requirements.ts

    3. Culture paragraphs are not requirements and dilute the comparison.

      Files src/requirements.ts

    done when · tick each as it passes
    watch out
    • Reducing a posting to a keyword list turns a requirement like experience leading a small team through a migration into the word migration, and then matching becomes a word game rather than a comparison. Keep requirements as quoted sentences so the user can see what is actually being asked for.
  3. Evidence, or its absence, stated plainly

    Each requirement is matched to CV text or reported as unevidenced.

    1. So the judgement belongs to the person rather than the tool.

      Files src/match.ts

    2. They call for completely different responses.

      Files src/gaps.ts

    3. A percentage hides exactly the distinction that matters.

      Files tests/no-scores.test.ts

    done when · tick each as it passes
    watch out
    • Reporting a partial match as a percentage hides whether the CV said something adjacent or nothing at all, and those need completely different responses from the person. Say absent, weak or evidenced, and quote the text in every case so the judgement is theirs.
  4. Suggestions that do not write your CV

    You are told what is missing, not given sentences to paste in.

    1. What did you actually do, rather than here is what they wanted.

      Files src/suggest.ts

    2. Its absence is the design. A pasted claim is a lie at interview.

      Files tests/no-generation.test.ts

    3. Some requirements genuinely do not apply to you.

      Files src/suggest.ts

    done when · tick each as it passes
    watch out
    • Generating a bullet point for a gap invites someone to paste in a claim about experience they do not have, which is a lie on a CV with their name on it and is discovered at interview. Ask what they actually did rather than supplying what the posting wanted to hear.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more career.