AI writing that cannot make things up.
A job-application assistant is a uniquely unforgiving place for a language model: a single fabricated line about your own history is a real-world harm, not a bad paragraph. So the interesting part of this project was never the generation. It was building a verifier with the authority to refuse it.
Public-safe by design
This page describes mechanisms, not content. It contains no application material, personal data, employer names, credentials, or model prompts.
- verification engine
- 668
- test cases
- 671
- external dependencies
- 0
- default on error
- deny
The problem
Fluency is not evidence
A model asked to describe your experience will produce something plausible whether or not it is true — and plausible is exactly the failure mode you cannot catch by reading. Reviewing output line by line does not scale, and 'the prompt says not to invent things' is not a control.
The design premise is that the model is an untrusted component. Every line it produces is treated as a claim requiring evidence, and the system's job is to decide — mechanically — whether that evidence exists. What ships is not what the model wrote; it is what survived.
Architecture
Two layers, and the cheap one goes first
A deterministic gate that cannot be fooled by fluency, followed by a model that judges meaning. Order matters: the layer with no failure modes runs first and rejects the easy cases for free.
- 01
Resolve every citation
Each generated line must reference fact ids that actually exist in the source set. An unresolvable id is not a warning — it is a violation, before any model is consulted.
- 02
Require whole-line containment
The line must appear complete inside a cited claim excerpt. Partial character overlap is explicitly rejected: that is the bypass where a fabrication hides behind an unrelated claim that happens to share a substring.
- 03
Judge entailment
Only lines that survive the deterministic gate reach the model. A schema-constrained judge rules on whether the claim actually entails the line, per sentence rather than per paragraph.
- 04
Fail closed at every seam
A thrown call, an unparseable reply, an unknown verdict token, or a missing verdict for any index all resolve to a violation. On a self-contradicting reply the worst verdict wins, so a duplicate pass can never clear a flagged line.
The detail that matters
Containment, not overlap
The single most important line of logic in the system is the one that decides what counts as 'covered by a source'. Getting it slightly wrong opens a hole wide enough to drive a fabrication through.
claim → “Shipped the billing rewrite in Q3.”line → “Shipped the billing rewrite for 40M users.”overlap check → shares “Shipped the billing rewrite”verdict → PASS ✕ fabrication ships
claim → “Shipped the billing rewrite in Q3.”line → “Shipped the billing rewrite for 40M users.”containment check → line ⊄ claimverdict → VIOLATION ✓ held back
The uncited tail is where invented specifics live — a number, a scale, a seniority. Requiring the whole line to sit inside the cited excerpt closes that gap, and pushing the digit and production-verb checks down to the sentence level stops a single citation from laundering a paragraph. Everything else in the engine follows from taking this one rule seriously.
Design decisions
Four choices that made it trustworthy
The gate contains no model
The first layer is pure, deterministic and offline. It cannot hallucinate, cannot be prompt-injected, and costs nothing to run — so the expensive, fallible layer only ever sees candidates that already passed a hard check.
The engine has no dependencies
The verifier is a standalone package with zero external imports across its modules. Domain knowledge enters only through three injected values — a ruleset, a document model, and a judge function — so the same engine verifies different document formats without forking, and swapping model providers touches one argument.
Verification outranks generation
Violations are fed back for a bounded number of corrective regenerations. A judge outage is detected as a distinct failure so retries never burn model calls on an uncurable error, and a failed validation surfaces rather than silently shipping.
The autofill never submits
The browser extension writes values into application forms, highlights them and shows a review banner. It never calls submit, never clicks an apply or continue control, and never advances a wizard. The human remains the last step by construction.
What it demonstrates
The transferable part is the harness
Nothing here is specific to job applications. The pattern — deterministic gate, model judge, fail-closed seams, an engine that owns no domain knowledge — applies anywhere a language model's output has consequences.
Grounding
Every claim resolves to a source fact, or it does not ship.
Evaluation
671 test cases pin the verifier's behaviour, including its refusal paths.
Portability
Zero-dependency core; provider and document format are injected, not assumed.
Outcome and learning
The useful question is not “is it good?” but “what would make it refuse?”
Building this changed how I scope every AI feature since. The generation is rarely the hard part; the hard part is deciding, in code, what the system is not allowed to say — and then making the failure path the default rather than the exception. A verifier that fails open is decoration.
The product itself remains private. A walkthrough of the engine and its refusal paths is available for interviews and technical discussions.