This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
The Problem With Résumés: Professional Claims Need Citations
Friday, 18 September 2026
A résumé should work like a scientific paper: human-written prose for communication, machine-readable structure for discovery, and references that connect claims to evidence.
As I once more hunt for my next paying gig (LinkedIn), I again face my nemesis: updating my résumé, CV, professional profile, or whatever we're calling the bloody thing this week. I have 35 years of professional experience and more than 50 gigs across full-time and contract work. Some lasted years. Some lasted weeks and involved fascinating technology. One was three months of distributed computing for an intelligence service. Another was a steganographic messaging system I built in my spare time for a domestic violence charity. Others were mostly firing and hiring developers. It is all potentially relevant, but how do I choose? Why would I leave out one role and include another?
Compressing all of that into one document which is useful to both people and machines is a task I cannot successfully complete. I know there is supposedly a ruleset for a successful résumé, but I cannot see it. I do not know:
- what the definitive rules are;
- who decided they were definitive;
- or what evidence supports them.
The document is supposedly prose for a human, yet it needs the right structure, phrases and keywords to survive an ATS, recruiter search and whatever model has been bolted onto the process this month.
The modern résumé is an odd document.
A few months ago I started lucidRESUME, a research project based around an evidence ledger for professional experience. Having to look for a job again gave me a reason to return to the underlying problem. This article is the result so far.
NOTE: lucidRESUME is a research project, not a finished end-user product. It is deliberately complex and changes as I test new ideas. Feel free to have a play, but I am not accepting feature requests or pull requests at present.
This is part one: source documents become a reviewed evidence ledger, then that ledger produces résumés without being re-inferred at render time. In part two, the job form becomes another projection: Chrome's on-device model maps unfamiliar form questions back to this same evidence without inventing answers. Part three compiles a real role-specific résumé from my complete career record, with cJobML references linking its compressed statements back to the fuller transcript and public artefacts.
Scientific Publishing Already Solved This Split
Scientific papers have served human readers and machine systems at the same time for years. JATS provides a machine-readable model for journal articles, while services such as Crossref use structured metadata and persistent identifiers to make scholarly work discoverable and connected.
- The prose communicates an argument to people.
- Structured metadata makes the work discoverable to machines.
- Citations connect individual claims to supporting material.
- References let either reader move from a summary to higher-resolution evidence.
A paper does not force every detail of its datasets, methods and prior work into the prose. It says what matters for the argument and provides routes to the rest. Search indexes can remain explicit and repetitive without making the paper itself read like a database export.
Why Scientific Publishing Works This Way
Science is cumulative. A paper is not meant to stand alone as a polished piece of writing. It joins a body of work. Its authors inherit methods, definitions, results and disagreements from other people, then leave enough structure for the next person to inspect and extend what they have done. This is the practical meaning behind standing on the shoulders of giants.
Citations make that cumulative process possible. The ICMJE recommendations tell authors to cite original research directly where possible and to verify their references. That discipline is not decorative bibliography. Citations perform several jobs at once:
- Justification: they show why a claim is present.
- Provenance: they identify where an idea, method or result came from.
- Navigation: they let a reader move from a summary to the underlying work.
- Attribution: they give credit to the people who produced that work.
- Challenge: they expose enough of the chain for somebody to question it.
- Reuse: they let later work build on a specific source rather than repeat an unsupported assertion.
Structured metadata solves a different problem. Titles, authors, dates, subjects, identifiers and abstracts let catalogues, search engines and research tools find the paper without requiring its prose to be rewritten for each index. The prose, metadata and citations cooperate, but none is forced to impersonate the others.
A career is cumulative too. Later roles build on earlier skills, projects, decisions and results. Yet a résumé usually throws away the links between them. It presents the latest compressed narrative while leaving the reader to guess which prior work supports each statement. Bringing citations to professional claims restores that missing chain.
Résumés have the prose and some crude metadata, but effectively no citation system. Their most important statements are isolated assertions:
Designed and delivered a high-throughput distributed platform.
The reader can believe that or not. There is no standard route from the sentence to the role, dates, technical context, design document, repository, article or other material which justifies it.
What I want is a traversable professional claim:
flowchart LR
C[Professional claim] --> R[Role or project]
R --> D[Dates and context]
D --> A[Supporting artefact]
A --> V[External verification where available]
classDef claim fill:none,stroke:#89b4fa,stroke-width:2px
classDef context fill:none,stroke:#f9e2af,stroke-width:2px
classDef evidence fill:none,stroke:#a6e3a1,stroke-width:2px
class C claim
class R,D context
class A,V evidence
That does not prove the claim true. Citations do not magically make scientific papers true either. They make claims inspectable, attributable and challengeable. A reader can follow the reasoning, judge the source and disagree.
For a machine, this distinction is even more useful. “Kubernetes appears in this document” is not the same statement as “the candidate claims a particular use of Kubernetes and links it to contemporaneous code, documentation, an article or an employer attestation.” One is a keyword hit. The other is an evidence graph.
We already have an enormous ecosystem of AI tools trained to extract claims, follow citations, assess evidence quality, identify unsupported statements and summarise papers. Applying the same pattern to résumés is hardly speculative. What is strange is continuing to feed those systems flattened prose and asking them to reconstruct the evidence graph for every application.
This is the thesis the rest of the article follows:
A résumé should work like a scientific paper: human-written prose for communication, machine-readable structure for discovery, and references that connect claims to evidence.
The Missing Layer in a Modern Résumé
The résumé is increasingly written with one AI and first read by another. It must be parseable and explicit enough for an ATS, but readable and selective enough for a person. Only after passing the machine may it reach a human, at which point it must work as a concise and credible career narrative.
One document is therefore being asked to do two different jobs:
- Provide explicit, structured and searchable data for machines.
- Provide selective, readable and persuasive prose for humans.
Good human prose compresses. It avoids repetition, relies on implication and varies its vocabulary. Good machine data is explicit, repetitive and predictable. Optimising one representation for both readers damages both.
The missing piece is not more keywords. It is the citation layer connecting the human statement to a richer, machine-readable account of the claim and its evidence.
Having studied clinical psychology, I was taught to be almost paranoid about references. The running joke was that if you wrote “the sky is blue,” somebody would ask for a reference to a smart person agreeing.
It is odd that résumés receive so little of the same discipline. Professional claims influence consequential decisions, yet “distributed systems,” “technical leadership” and “performance engineering” usually appear without citations. Synthesising a plausible document now takes seconds. Employer reference checks cannot provide a detailed, scalable answer for every claim in hundreds of applications.
The answer is not to demand cryptographic proof of an entire career. It is to make important claims traceable, so a person or machine can inspect why the document is entitled to make them.
The Loss Functions Are Different
“Loss function” is machine-learning language for the thing a system is trying to minimise. In ordinary terms, it is how we decide whether an output is getting better or worse.
Human résumé prose tries to minimise:
- reading effort;
- repetition;
- irrelevant detail;
- loss of voice;
- and the time needed to understand why somebody's work mattered.
A machine-readable résumé tries to minimise:
- ambiguity;
- missing entities and dates;
- inconsistent terminology;
- implicit relationships;
- and unsupported or untraceable claims.
Those targets conflict when they share one representation. A person does not want “Kubernetes” repeated in every paragraph merely to improve retrieval. An ATS does not reliably understand that “operated the production platform” implies a particular technology, capability, period and level of responsibility.
Optimising only for people can hide useful structure. Optimising only for machines produces keyword-stuffed prose which is tedious, generic and less credible. Trying to average the two gives us the modern résumé: not quite good prose and not quite good data.
Scientific publishing avoids this compromise by separating the targets:
flowchart TB
E[Reviewed experience and evidence]
H[Human-written prose]
M[JobML]
HL[Clarity, voice, selection and context]
ML[Explicitness, retrieval, coverage and structure]
C[Citation constraint]
E --> H
E --> M
H --> HL
M --> ML
HL --> C
ML --> C
C -. must resolve to .-> E
classDef source fill:none,stroke:#a6e3a1,stroke-width:2px
classDef human fill:none,stroke:#89b4fa,stroke-width:2px
classDef machine fill:none,stroke:#cba6f7,stroke-width:2px
classDef constraint fill:none,stroke:#f9e2af,stroke-width:2px
class E source
class H,HL human
class M,ML machine
class C constraint
The citation is the constraint between them. Each representation can optimise for its own reader, but neither gets to invent a different underlying career. Human prose can compress. JobML can remain high-resolution. Both must lead back to the same reviewed evidence.
What Does the Research Actually Say?
There is plenty of research into hiring signals and discrimination, but surprisingly little experimental evidence for an ideal section order, page length, bullet count or keyword density. Most supposedly important rules seem to be repeated advice from recruiters, résumé services and ATS vendors. Waves at SEO people, another field where much of the advice is spells and divination.
Conventional Layouts Usually Win
A controlled study by Arnulf, Tegner and Larssen found that formal layouts beat creative ones even when the candidate information was equivalent. It does not reveal the One True Template. It shows that presentation changes perception and predictable structure makes evidence easier to find.
Detail, Clarity and Structure Matter
A 2025 study by Wingate, Robie, Powell and Bourdage followed 183 students through real applications. Clearer, more detailed and better-organised applications received more interviews and found work faster, even after controlling for experience, achievements and tailoring. The sample was narrow, but the useful conclusion is modest: compositional quality matters.
There is a wrinkle. If an LLM can improve clarity in seconds, writing quality may still influence selection while saying less about the candidate's own ability or effort. The signal survives as its meaning erodes.
Recruiters Evaluate Signals
Experimental studies show employers responding to visible signals such as experience, qualifications, grades and skills. The value of each changes by role and employer. Eye-tracking research also suggests selective scanning, although it does not justify the folklore that every recruiter reads a CV for exactly six or seven seconds.
All I think we can safely say is that recruiters inspect limited evidence and use it to infer qualification and fit.
The résumé is an information-retrieval interface pretending to be an essay.
The Folklore Is Not Evidence
There is little strong independent evidence that:
- Every résumé must be exactly one or two pages.
- There is one universally optimal section order.
- Every achievement must use the same action-result formula.
- PDF always beats DOCX, or DOCX always beats PDF.
- A particular keyword density will satisfy an ATS.
- A professional summary always helps or always hurts.
ATS products are proprietary, varied and continually changing. The safest advice remains painfully generic: use predictable headings, preserve the reading order and make the evidence easy to recover. That is not optimisation. It is damage limitation.
One Ledger, Three Publication Resolutions
The scientific publishing model gives the published résumé three distinct layers, but the implementation needs one more thing behind them: a canonical career ledger.
| Scientific paper | Evidence-aware résumé | Purpose |
|---|---|---|
| Human prose | Human-written Markdown | Communicate clearly to a person. |
| Indexing metadata | JobML entities, concepts and dates | Make the document explicit and discoverable to machines. |
| Citations and references | Inline cJobML numbers and a References section | Connect each important claim to its justification. |
The ledger is the application's complete working record. It can retain imported files, rejected extraction candidates, merge decisions, private observations, the evidence and skill ledgers, article summaries, repository descriptions, embeddings and role centroids. It is deliberately richer than anything I would publish.
JobML is now the portable envelope around that record, not another name for the
record itself. A career_record JobML document is the complete interchange
projection. A resume JobML document is a selected role-specific projection.
cJobML is the compact citation projection attached to the résumé a person sends.
canonical career ledger
├── JobML career_record complete portable projection
├── JobML resume role-specific machine projection
└── cJobML compact published citations
These layers can travel together, but they are not copies of one another. The prose can remain concise, selective and recognisably human. The machine layer can repeat skill names, use stable identifiers and preserve details which would make the prose tedious. A published résumé only needs the compact citations. The full editing record can live at a linked JobML endpoint, much as a paper can point to supplementary data.
The citation is what keeps the two honest:
human claim
↓
JobML claim identity
↓
cited prose or external source
↓
reviewed evidence
Without that link, a machine-readable skills list is merely a second set of assertions. It can say “distributed systems” without identifying which project demonstrates it, what the candidate did, when it happened or what material still exists to inspect.
The human résumé is authoritative about what its prose says, but it is not a complete career record. The JobML layer can be richer, link to external sources and support shorter role-specific documents. It must not overwrite the author's words or turn an inference into fact.
The ledger also needs an identity for the work which is separate from the name on an invoice. My Seamcor work continued through Rooikat Investment when the contracting entity changed for legal reasons. It remained the same product, team and delivery responsibility. Treating the two company names as two jobs would shorten the apparent tenure, duplicate the product and make the history less accurate. The reviewed record therefore keeps both legal entities and their source dates, but publishes one continuous product engagement.
That is the résumé equivalent of resolving two citations which describe the same study. We retain what each source actually says, record the reviewed relationship between them, and avoid counting the same underlying work twice.
This also exposes drift. If an edited paragraph no longer supports a claim, the citation becomes stale. A skill cannot quietly survive in a detached keyword list after its only supporting passage has disappeared.
JobML Is the Portable Citation Record
JobML 0.1 is the small interchange format I built around that idea. The editable source contains ordinary Markdown and a fenced YAML block. The Markdown is the authored document. The YAML records claims and points each one back to evidence in the prose or to an external source.
The rule at the centre of it is:
A JobML claim MUST be traceable to the human-readable or external evidence that supports it, and machine-derived information MUST NOT silently become evidential fact.
Here is a complete miniature example:
# Jane Smith
## Experience
### Example Corp {#example-corp}
Led the modernisation of a high-volume ASP.NET Core platform.
---
```jobml
jobml:
version: "0.1"
profile: career_record
purpose: >
Machine-readable representation of claims made by this resume. Claims are
supported by human-readable prose or external evidence. Absence of a claim
does not imply absence of a skill or capability.
semantics:
- Every substantive claim should be supported by one or more evidence references.
- Do not infer unsupported claims or treat machine-derived suggestions as evidence.
- Use both the human-readable prose and JobML when evaluating this resume.
- Treat JobML as a higher-resolution description, not as replacement prose.
document:
id: jane-smith-career-record
language: en-GB
entities:
- id: example-corp
type: experience
name: Example Corp
source: "#example-corp"
claims:
- id: platform-modernisation
subject: example-corp
statement: Led modernisation of a high-volume ASP.NET Core platform.
concepts:
skills: [aspnet-core]
supported_by:
- type: prose
ref: "#example-corp:p1"
fingerprint:
text: "fnv1a64:78cf6acd1fd870af"
selector:
type: TextQuoteSelector
exact: Led the modernisation of a high-volume ASP.NET Core platform.
- type: repository
uri: https://github.com/example/platform
- type: article
title: Operating ASP.NET Core at Scale
authors: [Jane Smith]
publisher: Jane's Engineering Notes
published: 2026-04-12
uri: https://example.com/aspnet-at-scale
concepts:
- id: aspnet-core
type: skill
name: ASP.NET Core
aliases: [ASP.NET, .NET web development]
- id: engineering-leadership
type: capability
name: Engineering Leadership
semantic_spaces:
- id: article-demo-v1
model: example/article-demo-v1
dimensions: 4
normalization: l2
role_centroids:
- id: head-of-engineering
name: Head of Engineering
space: article-demo-v1
derived_from: [engineering-leadership]
vector: [0.12, -0.34, 0.56, 0.75]
```
Read cold, its intent should be obvious. JobML is schema-checkable YAML, but the explanation travels inside the file. The purpose and semantics tell an unfamiliar LLM what the document means and what it must not infer.
The real exporter uses the local all-MiniLM-L6-v2 ONNX model and writes its
384-dimensional space descriptor, concept vectors and shipped role centroids
into career_record. Those values help another processor reproduce semantic
selection. They are explicitly derived artefacts: a nearby vector can rank a
claim, but it cannot make the claim true or become evidence for it.
A formal JSON Schema supports deterministic tools. There is also a cold-parser test: give the document to a general model with no JobML prompt and ask it to identify the claims, evidence and unsupported assertions. If it cannot work that out from the file, the format has failed.
The career_record representation is useful while writing and between tools
because it contains the original
passage, stable selector, fingerprint, review state and provenance. It is much too
large to append to every résumé. Scientific papers already have a better answer:
put small numbered links in the prose, a compact reference list at the end, and a
link to the full JobML record when somebody needs the detail.
cJobML Is the Published Reference List
cJobML 0.1 is the deliberately lossy publication projection of JobML. It is not another source format and it is not another ledger to keep in sync. lucidRESUME produces it deterministically from accepted links in full JobML:
Led the modernisation of a high-volume ASP.NET Core platform. [[1]](#ref-1)
## References
cJobML 0.1: xref [n] in prose resolves to ref [n]. Full JobML: <https://example.com/jane-smith.jobml>.
<a id="ref-1"></a>[1] Jane Smith. “Operating ASP.NET Core at Scale.” Jane's Engineering Notes, 12 Apr 2026. [Article] <https://example.com/aspnet-at-scale>.
That is close to the convention a scientific reader already understands. cJobML
borrows the useful concepts from JATS rather than its XML syntax: an inline
xref
points into a reference list, each numbered item is a ref, and the full-JobML
link plays the role of a
self-uri
or supplementary record.
The compact form leaves out the quoted passage, selector, checksum, drift state, concept graph and review history. Those are editing machinery and remain in full JobML. The résumé keeps only what publication needs: a number beside the claim, a recognisable source at the end, and a route to the full JobML career record.
Reference numbers identify evidence sources, not claims. If three claims cite the same article or repository, they reuse the same number. Rendering does no NER, semantic search or LLM inference. It only numbers external evidence which is already attached to an accepted claim.
That also makes linked posts useful without pretending they prove too much. An article can demonstrate knowledge, authorship and the reasoning available at its publication date. It does not automatically prove that its author used the technology in production or held a particular responsibility. Full JobML records the exact relationship. cJobML publishes the citation.
The Citation Must Survive Editing
An inline citation which silently points at the wrong paragraph is worse than no citation at all.
Paragraph numbers break when somebody inserts a paragraph. Exact text breaks when punctuation changes. Semantic similarity can suggest candidates, but must not reinterpret weaker prose as stronger evidence. If:
Led the modernisation...
becomes:
Contributed to the modernisation...
the old claim cannot remain green merely because the sentences occupy the same position and look semantically similar.
JobML uses three ways to find the cited passage:
- A readable structural reference such as
#example-corp:p1. - A fast FNV-1a 64-bit fingerprint of the normalised evidence text.
- A W3C Web Annotation-style
TextQuoteSelectorcontaining the exact quote and, where useful, its surrounding context.
The hash is non-cryptographic because it detects editing drift, not fraud. The reference says where the evidence should be. The fingerprint says whether it is still the reviewed text. The quote selector helps recover it after a move.
Reconciliation produces four honest states:
| State | Meaning |
|---|---|
valid |
The cited evidence resolves and still matches. |
changed |
The passage exists, but it is no longer the reviewed text, or it moved uniquely. |
missing |
The evidence can no longer be found. |
ambiguous |
More than one passage could be the citation target. |
Nothing is silently repaired. A unique move or edit can be offered for acceptance. Missing and ambiguous citations need a human decision. Accepted claims with unresolved evidence block publication.
You can reopen the file after editing and see exactly what JobML believed, why it believed it and what changed underneath it.

The important part of that screenshot is not the red state by itself. The prose, claim, reference and diagnostic remain visible together. Drift is something the author can resolve in context, not a warning buried in an export log.
Live Evidence, Not a Report You Run Later
References in a paper are useful because the author can see and maintain them while writing. JobML needs the same property. If its model is hidden until an export or validation step, it will drift like every other detached skills list.
The lucidRESUME editor therefore acts partly as a live citation manager. It shows three things together:
- the editable Markdown + JobML source
- the human résumé preview
- live evidence cards and validation diagnostics
Selecting an evidence card jumps to its source span. Editing that span updates its state. Claims extracted during ingestion begin as origin: derived and review: required, and count for nothing until accepted. Publishing commits the Markdown, reviewed JobML and document fingerprint as one snapshot.

It works like following a citation in a paper. The prose stays readable and the justification is one click away.
The document view should be equally direct. Markdown remains the editable source, but the default visual view after ingestion is the actual résumé page produced by the selected Word template. As the Markdown changes, lucidRESUME debounces the edit, exports a fresh DOCX and asks Morph to render its pages. The editor therefore has three views of the same revision:
- Document: the live Word-layout projection which will be exported;
- Write: the authoritative Markdown source;
- Markdown preview: a fast structural preview while typing.

The JobML and evidence cards remain beside all three. Changing a template changes layout, typography and pagination. It does not run extraction again, alter the ledger or rewrite the prose.
Different Roles Need Different Resolution
Scientific publishing already works at several resolutions. A title identifies the subject, an abstract compresses the argument, the paper gives the working account, and supplementary material preserves details which would obstruct the main text. Those layers differ in resolution without becoming different research.
A role-specific résumé can work in the same way. Authoritative does not mean exhaustive. A principal engineer version might retain the technical detail of an architecture migration. A CTO version might summarise the same evidence around risk and commercial outcome. Another application might omit it.
JobML can remain high-resolution while the prose is compressed. It can also expose a role-specific subset when the full graph would be irrelevant. The resolution changes. The evidence does not:
flowchart TB
E[Reviewed evidence graph]
ER[Detailed engineering résumé]
LR[Compressed leadership résumé]
MR[Role-specific machine coverage]
C[Same cited evidence]
E --> ER
E --> LR
E --> MR
ER --> C
LR --> C
MR --> C
classDef source fill:none,stroke:#a6e3a1,stroke-width:2px
classDef human fill:none,stroke:#89b4fa,stroke-width:2px
classDef machine fill:none,stroke:#cba6f7,stroke-width:2px
class E,C source
class ER,LR human
class MR machine
You can summarise it. You cannot make it up. An LLM may offer a draft or sample, but that is not the point of the system and it is not authoritative. The person reviews, edits and owns the prose. Changed text is linked and reconciled with the ledger before publication. Rendering does none of that work. It only projects already reviewed ledger records into a role-specific document.
That split is the product. Human prose should remain natural writing for human readers. JobML gives ATS and AI systems the explicit, high-resolution detail they need, with citations. lucidRESUME is not an application bot and it is not trying to make generated text pass as human text.
That distinction matters. The output pipeline is not a final prompt which asks a model to rediscover the candidate from source documents. Extraction happens once at ingestion, using deterministic parsing, NER, and optionally an LLM. Each result keeps its source, method, confidence, review state, and evidence fingerprint. The ledger is then kept current as sources change. Markdown, JobML, Word, and PDF are projections of a particular ledger revision. They are not new interpretations of it.
From a Complete Career to an Appropriate Résumé
The useful product surface is much smaller than the machinery underneath it:
Paste the job. Get the right version of you.
The hard work happens earlier. Old résumés, a LinkedIn export, repositories,
projects and linked articles become one reviewed career ledger and a deliberately
long human career transcript. JobML career_record is the portable expression
of that work.
A job description is then a query, not a writing prompt. It changes which parts of the record are selected, their order and the resolution at which they are presented. It does not get permission to modify the candidate.
flowchart LR
L[Canonical career ledger] --> C[JobML career_record]
J[Job description] --> Q[Requirement query]
C --> S[Evidence selection]
Q --> S
S --> H[Role-specific human résumé]
S --> M[JobML resume]
M --> R[cJobML references]
H --> O[Word or PDF]
R --> O
classDef source fill:none,stroke:#a6e3a1,stroke-width:2px
classDef process fill:none,stroke:#89b4fa,stroke-width:2px
classDef output fill:none,stroke:#cba6f7,stroke-width:2px
class L,C,J source
class Q,S process
class H,M,R,O output
Semantic concepts and role centroids help retrieve the relevant evidence for a Lead Developer, Head of Engineering, CTO or VP Engineering role. Their influence ends at ranking. They remain derived indexes, much like the search index around a scientific archive; they are not citations and they cannot establish a fact.
Their score is evidence coverage, not a hiring verdict. A record can contain language which is semantically close to almost every paragraph in a vacancy and still miss a hard requirement such as a qualification, a particular scale of leadership or direct experience training foundation models. Calling that number "fit" would turn a retrieval measurement into an unsupported career claim.
The human résumé starts from human prose in the complete transcript. Usually it
is selected and compressed. It may be tightened with assistance, but the result
remains an editorial draft until the person accepts it. The accompanying JobML
resume preserves the selected claim identities, cJobML adds the compact
references, and document.full_jobml provides the route back to the published
career record.
This is a compiler in the useful sense. The same reviewed source can produce different documents without becoming different people. The résumé changes with the question. The evidence does not.
Importing Several Imperfect Résumés
Most people begin with resume-final.docx, resume-final-2.pdf, an old LinkedIn export and three role-specific variants which disagree about dates and wording.

lucidRESUME imports multiple documents, parses experience, education, projects and skills, then presents merge candidates. Finding "Kubernetes" in two files gives us something to review. It does not establish a fact.
The real record produced a more interesting merge than a spelling variation. LinkedIn listed Seamcor and Rooikat as overlapping positions. A contract named Rooikat as the client but explicitly described the work as development, deployment and management of the Seamcor application and architecture. I could then confirm that the work began in December 2022 and continued to May 2024 on the same product. The accepted record became:
Head of Software / Contract Head of Development
Seamcor Ltd / Rooikat Investment Ltd
December 2022 to May 2024
One product and team; contracting entity changed for legal reasons.
Recruited eight engineers and led a mixed-seniority team of more than ten.
No parser could responsibly infer all of that from one document. Equally, a model should not smooth the overlap into a plausible story and forget where it came from. The ledger retains the source observations, the explicit continuity decision and the reviewed dates. Every later résumé receives the same chronology without reinterpreting the imports.
There are two ways this can go wrong:
- structural uncertainty: did the parser correctly recognise the role, date or paragraph?
- evidential uncertainty: does that paragraph actually justify the proposed claim?
Layout detection, deterministic parsing and a local model can improve the first. The second is a review decision. LLamaSharp and the local grug-9b GGUF model assist extraction. Imported prose and explicit human acceptance are authoritative.
The important boundary sits between extraction and acceptance. A parser may identify a plausible employer, date or skill, but uncertainty must not quietly become professional fact as the document moves through merge, drafting and publication.
Extraction Produces Candidates, Not Facts
The ingestion pipeline deliberately combines several narrow signals. Structural parsing finds sections and dates. Local NER identifies organisations, job titles and skills. A taxonomy catches exact known terms. Agreement raises confidence, but every result still carries its source and review state.
This is the useful bit of the extraction pipeline, shortened slightly for the article:
var all = new List<ExtractedEntity>();
foreach (var detector in detectors.OrderBy(d => d.Priority))
{
var found = await detector.DetectAsync(context, cancellationToken);
all.AddRange(found);
}
var fused = all
.GroupBy(entity => (
entity.Classification,
entity.NormalizedValue.ToLowerInvariant()))
.Select(group =>
{
var best = group.OrderByDescending(e => e.Confidence).First();
var sources = group.Select(e => e.Source).Distinct().Count();
best.Confidence = Math.Min(1.0,
best.Confidence + 0.08 * (sources - 1));
return best;
});
That code does not write résumé prose. It creates reviewable observations for the
ledger. A model can help recognise that K8s and Kubernetes are related, but it
cannot promote the relationship into accepted experience.
Jev Resolves Bounded Import Ambiguity
NER is good at finding spans. It can tell us that Example Corp, London and
Platform Group look like named entities. It is less good at answering a
document-specific question such as "which of these organisations is the employer
for this experience block?"
That is the narrow experiment I am running with Jev. Jev accepts shared state and typed questions, then returns a choice and a probability distribution. It does not get an empty text box in which to write a more convenient answer.
document layout and text
-> deterministic parser and local NER
-> closed candidate set
-> Jev chooses a candidate or abstains
-> probability and winner-margin policy
-> human review
-> accepted ledger record
The first experiment handles three ambiguities:
- classify a top-level section when heading rules abstain;
- select the résumé owner's name from positional and NER candidates;
- select an employer from organisation spans when an experience entry has no deterministic company value.
Suppose an imported block contains these candidates:
{
"question": "Which candidate is the employer for this experience entry?",
"choices": ["Example Corp", "London", "Platform Group", "none"]
}
Jev may select Example Corp or none. It cannot return Google, because
Google was never observed. lucidRESUME accepts the decision only when the
selected probability is at least 0.80 and the winner beats the runner-up by at
least 0.20. Otherwise it becomes a review item.
Every decision records the source hash, candidate-set hash, probability distribution, model version and acceptance result. If the source changes, the old decision is stale. Jev is a hosted service and is disabled by default; enabling it sends bounded, contact-redacted passages to that provider. The local NER and deterministic paths continue to work without it.
This is where Jev belongs. It helps turn messy source documents into typed review candidates. It is not called while exporting a résumé, and it does not sit inside the browser form filler. By the time either projection runs, the ambiguity should already have been resolved into accepted ledger data.
The drift check is intentionally much less glamorous:
public static string Fingerprint(string text)
{
const ulong offsetBasis = 14695981039346656037;
const ulong prime = 1099511628211;
var hash = offsetBasis;
foreach (var value in Encoding.UTF8.GetBytes(NormalizeText(text)))
{
hash ^= value;
hash *= prime;
}
return $"fnv1a64:{hash:x16}";
}
FNV-1a is fast enough to run continuously while somebody types. It is not there to prove authorship or resist an attacker. It answers one precise question: is this still the normalised passage which a person reviewed when accepting the claim? The stable reference and quote selector handle location and recovery.
Checking the Published Document With OpenResume
Producing valid PDF text is not the same as surviving a résumé parser, so I also
fed the generated PDF through the open-source
OpenResume parser using its real browser
interface. It recovered the candidate's name, email, GitHub link, summary,
skills, experience achievement, its [1] marker, the compact reference, both
URLs and the full-JobML link.
OpenResume has a fixed model for profile, education, work, projects and skills, but no References section. It preserved the reference text as project content. That is a useful limitation to understand: an older parser can retain unfamiliar material without understanding its category.
That result is evidence, not a victory banner. It shows that the generated text, links and citation relationship survive one real, freely inspectable ATS-style parser. It does not prove compatibility with proprietary ATS products. It also suggests the right fallback: keep the reference list plain and compact, and let a JobML-aware parser recover its richer meaning without making an older parser fail the rest of the résumé.
The same document is also legible at two other levels. A deterministic cJobML parser can pair every inline number with its reference, while a general language model with no JobML-specific prompt can recover the cited claim, evidence URL and full-JobML URL. That is the progressive-enhancement goal: ordinary readers, existing résumé parsers and JobML-aware tools can each take what they understand.
Why Not Extend an Existing Résumé Format?
I looked at the obvious candidates before inventing another acronym:
| Format | What it is good at | Why it is not the authoring model |
|---|---|---|
| JSON Resume | Portable structured résumé records and themes | Record-first, with no prose anchor, citation state or reconciliation lifecycle. It is a useful import/export target. |
| HR Open Standards | Broad recruiting-system interchange | Deliberately much larger than an evidence-aware writing format. |
| Europass | Rich public-employment exchange | Useful downstream, but too broad and exchange-oriented for live authoring. |
| h-resume | Human and machine content co-located in HTML | Skills remain assertions rather than evidence-linked claims with drift state. |
| Schema.org Occupation | Public linked data about people and occupations | A sensible web projection, not a document reconciliation model. |
| W3C Web Annotation | Anchoring annotations to changing text | Exactly the useful citation machinery, but intentionally not a résumé schema. |
JobML does not replace these formats. It borrows the useful selector bits from Web Annotation and can export to JSON Resume, Europass or Schema.org when needed.
This is how I intend to avoid accidentally founding the W3C of CVs. 😄
RAG, But With a Citation Discipline
The DocSummarizer pipeline handles parsing, segmentation and citations before the LLM sees the document. Reduced RAG narrows its input to useful signals and relevant evidence. lucidRAG keeps sentence-level links from answers back to their sources. DoomSummarizer uses the same idea for deep research. Generated synthesis is not the source. The evidence is.
JobML applies that discipline to a far smaller, stranger document.
When comparing a résumé with a job description, the path should be:
flowchart LR
J[Job requirement] --> S[Semantic concept]
S --> C[Reviewed candidate claim]
C --> R[Valid citation]
R --> E[Human prose or external evidence]
classDef requirement fill:none,stroke:#f38ba8,stroke-width:2px
classDef machine fill:none,stroke:#cba6f7,stroke-width:2px
classDef claim fill:none,stroke:#89b4fa,stroke-width:2px
classDef evidence fill:none,stroke:#a6e3a1,stroke-width:2px
class J requirement
class S machine
class C claim
class R,E evidence
That allows a coverage report to say:
ASP.NET Core ✓ directly evidenced
Kubernetes ✓ directly evidenced
SOC 2 ? related evidence; review required
Terraform ✗ no supporting evidence found
The last line is not permission for an LLM to sprinkle "Terraform" into the résumé. It means we found no evidence for it. So don't add it.
What JobML 0.1 Deliberately Does Not Do
The format supports Markdown, embedded YAML, entities, claims, concepts, aliases, evidence, drift detection and requirement coverage. It does not standardise a universal skill ontology, mandate embeddings, attest cryptographically, verify employers or integrate every ATS.
It never silently rewrites prose. Ask for a draft or role-specific sample and it can suggest wording. The result stays a draft until the author reviews, edits and accepts it. It cannot become evidence merely because a model wrote it.
A paper is not valuable because every sentence is magically true. It is valuable because you can follow important claims back to their justification, argue with them and revise them.
That is what I want from a résumé:
Do not merely tell me what this person claims. Let me follow the citation and see why the document is entitled to claim it.
Scientific publishing does not ask prose, metadata and references to do the same job. Neither should a résumé.
The prose communicates. JobML makes the document explicit and discoverable. Citations let a reader inspect why each claim exists. Together they allow one document to carry as much or as little detail as a role needs, while preserving a route back to the reviewed evidence behind every important machine claim.
That completes the first half of the pipeline: imperfect source documents have become a reviewed ledger, and every published résumé is a projection of it. In part two, I use Chrome's local Gemini Nano model to map unfamiliar job-form questions onto the published JobML career record. It is a useful demonstration of the boundary: the model may find evidence, but it still cannot author a new professional fact.
References
- Arnulf, J. K., Tegner, L. and Larssen, Ø. (2010). "Impression making by résumé layout: Its impact on the probability of being shortlisted." European Journal of Work and Organizational Psychology, 19(2), 221-230.
- Kessler, J. B., Low, C. and Sullivan, C. D. (2019). "Incentivized Resume Rating: Eliciting Employer Preferences without Deception." American Economic Review, 109(11), 3713-3744.
- Piopiunik, M., Schwerdt, G., Simon, L. and Woessmann, L. (2020). "Skills, signals, and employability: An experimental investigation." European Economic Review, 123.
- Törngren, S. O., Schütze, C., Van Belle, E. and Nyström, M. (2024). "We choose this CV because we choose diversity: What do eye movements say about the choices recruiters make?" Frontiers in Sociology, 9.
- Wingate, T. G., Robie, C., Powell, D. M. and Bourdage, J. S. (2025). "The Signals That Matter: Resumes, Cover Letters, and Success on the Job Search." International Journal of Selection and Assessment, 33(3).
- National Library of Medicine. Journal Article Tag Suite (JATS).
- Wang, X. OpenResume: Open-source résumé builder and parser.