When you build a tool that analyses CVs against job descriptions, one failure mode keeps you up at night: what if the system treats the job description as evidence about the candidate?
It sounds obvious. Of course a job ad saying "must have Python experience" shouldn't become evidence that the candidate has Python experience. But when you're building matching logic that ingests both a CV and a JD, that boundary is easier to cross than you'd think — especially if you're using embeddings or similarity scores that don't distinguish the source of a piece of text.
I built Wallbreak (https://wallbreak.co.uk), a UK job-search tool with CV analysis. Before I built any of the matching logic, I wrote what I called Gate B.
What Gate B actually is
Gate B is a hard rule in the analysis pipeline: job-description content cannot be promoted to candidate evidence. Ever.
In practice, this means the analysis pipeline maintains two strictly separate stores:
-
candidate_evidence: populated only from the CV the user uploads -
jd_requirements: populated only from the job description the user provides
When the matching logic runs, it compares these two stores against each other. It never reads from jd_requirements to fill a gap in candidate_evidence. A gap is a gap — it's surfaced as "your CV doesn't yet show this," not silently filled with requirement text.
This sounds simple. But maintaining it required being explicit about data flow at every layer of the pipeline. Every function that writes to candidate_evidence has to declare its source. If the source isn't the candidate's own CV, the write is rejected.
Why deterministic rules instead of embeddings
Most CV analysis tools use similarity scoring: embed the CV, embed the JD, compute cosine similarity, output a percentage. The problem is that this is opaque. A 73% match score doesn't tell you what's missing. It doesn't tell you which specific criteria you do and don't evidence. And it's easy to game — put enough keywords in a CV and the score improves regardless of actual experience.
I chose deterministic rule sets instead:
- ATS readability: structured checks for common ATS failure patterns (tables, graphics, non-standard headings, missing contact fields)
- UK formatting: checks for UK-specific norms (no photo, no date of birth, 2-page norm, reverse-chronological order)
- STAR-pattern evidence: checks whether work history items follow a Situation-Task-Action-Result structure or read as a list of duties
- Target-role alignment: checks whether the candidate's evidence uses the same language as the role's essential criteria
Each rule produces a yes/no or a specific gap. The output is a list of findings, not a single score. You can read each finding, understand exactly what triggered it, and fix it.
What this means for trust
The CV analysis is honest about what it can and can't know. It can tell you whether your CV has a STAR-pattern evidence gap for "project management." It can't tell you whether you're actually good at project management — and it doesn't try to.
This is a product decision as much as a technical one. I think the job-search tool market has a credibility problem because too many tools make claims that sound authoritative but can't be substantiated. "You're a 91% match" sounds precise. It isn't.
If you're building anything in this space, I'd encourage you to think carefully about what your tool actually knows versus what it's inferring. The distinction matters more than it might seem.
The stack
The backend is Python/FastAPI deployed on Railway. The CV parsing goes through a structured extraction layer before any analysis runs — that's also where Gate B is enforced. The frontend is React/Vite on Vercel.
The product is in beta. The analysis is not a trained model. AI features may have usage limits; pricing is not yet finalised. Feedback from builders is genuinely useful right now, particularly on the rule logic and where the gap explanations are or aren't helpful.
I'm the founder of Wallbreak. This is a first-person account of technical decisions I made. I'm not paid to write this and I have an obvious stake.
Top comments (0)