# The Problem With Résumés: Professional Claims Need Citations

<!--category-- AI, LLM, JobML, Résumés, RAG, Avalonia, Evidence, Open Formats -->

<datetime class="hidden">2026-09-18T12:00</datetime>

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](https://www.linkedin.com/in/scott-galloway-91608691/)), 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](https://github.com/scottgal/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.

[![lucidRESUME release](https://img.shields.io/github/v/release/scottgal/lucidRESUME?filter=v*&label=lucidRESUME&logo=github)](https://github.com/scottgal/lucidRESUME/releases)
[![Mostlylucid.Avalonia.UITesting on NuGet](https://img.shields.io/nuget/v/Mostlylucid.Avalonia.UITesting.svg?logo=nuget&label=Avalonia%20UI%20Testing)](https://www.nuget.org/packages/Mostlylucid.Avalonia.UITesting)

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](/blog/lucidresume-evidence-filler):
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](/blog/lucidresume-web-compiler), with cJobML references linking its
compressed statements back to the fuller transcript and public artefacts.

[TOC]

---

## Scientific Publishing Already Solved This Split

Scientific papers have served human readers and machine systems at the same time
for years. [JATS](https://jats.nlm.nih.gov/) provides a machine-readable model for
journal articles, while services such as
[Crossref](https://www.crossref.org/documentation/metadata-plus/) 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](https://www.icmje.org/recommendations/browse/manuscript-preparation/preparing-for-submission.html#references)
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:

```mermaid
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:

1. Provide explicit, structured and searchable data for machines.
2. 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](https://libguides.gold.ac.uk/psychology/referencing). 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:

```mermaid
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](https://doi.org/10.1080/13594320902903613) 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](https://doi.org/10.1111/ijsa.70022) 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](https://doi.org/10.1257/aer.20181714) 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](https://doi.org/10.3389/fsoc.2024.1222850) 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.

```text
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:

```text
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](https://github.com/scottgal/lucidRESUME/blob/main/docs/jobml-0.1-specification.md)
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:

````markdown
# 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](https://github.com/scottgal/lucidRESUME/blob/main/docs/jobml-0.1.schema.json) 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](https://github.com/scottgal/lucidRESUME/blob/main/docs/cjobml-0.1-specification.md)
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:

```markdown
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`](https://jats.nlm.nih.gov/archiving/tag-library/1.2d2/attribute/ref-type.html)
points into a reference list, each numbered item is a `ref`, and the full-JobML
link plays the role of a
[`self-uri`](https://jats.nlm.nih.gov/publishing/tag-library/1.4/element/self-uri.html)
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:

1. A readable structural reference such as `#example-corp:p1`.
2. A fast FNV-1a 64-bit fingerprint of the normalised evidence text.
3. A [W3C Web Annotation-style `TextQuoteSelector`](https://www.w3.org/TR/annotation-model/#text-quote-selector) containing 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 editor marking changed and missing evidence after the supporting prose is edited](lucidresume/03-jobml-drift-detected.png?width=1200&format=webp&quality=80)

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](https://github.com/scottgal/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.

![A selected evidence card links the human prose on the left to its JobML reference on the right](lucidresume/02-jobml-link-selected.png?width=1200&format=webp&quality=80)

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 live ATS Classic Word projection beside its evidence links and JobML](lucidresume/jobml-live-word-document-and-evidence.png?width=1200&format=webp&quality=80)

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:

```mermaid
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.

```mermaid
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.

![An imported Word résumé rendered as pages beside the extracted structure and quality report](lucidresume/01-first-docx-with-experience.png?width=1200&format=webp&quality=80)

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:

```text
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](https://github.com/SciSharp/LLamaSharp) and the local [grug-9b GGUF model](https://huggingface.co/ProCreations/grug-9b-gguf) 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:

```csharp
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](https://vercel.com/ai-gateway/models/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.

```text
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:

```json
{
  "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:

```csharp
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](https://github.com/xitanggg/open-resume) 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](https://jsonresume.org/schema) | 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](https://schema.hropenstandards.org/) | Broad recruiting-system interchange | Deliberately much larger than an evidence-aware writing format. |
| [Europass](https://europass.europa.eu/system/files/2020-08/ECV_Schema_Documentation_v3.0.0_20200602.pdf) | Rich public-employment exchange | Useful downstream, but too broad and exchange-oriented for live authoring. |
| [h-resume](https://microformats.org/wiki/h-resume) | Human and machine content co-located in HTML | Skills remain assertions rather than evidence-linked claims with drift state. |
| [Schema.org Occupation](https://schema.org/Occupation) | Public linked data about people and occupations | A sensible web projection, not a document reconciliation model. |
| [W3C Web Annotation](https://www.w3.org/TR/annotation-model/) | 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](/blog/docsummarizer-rag-pipeline) handles parsing, segmentation and citations before the LLM sees the document. [Reduced RAG](/blog/reduced-rag) narrows its input to useful signals and relevant evidence. [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) keeps sentence-level links from answers back to their sources. [DoomSummarizer](/blog/doomsummarizer-deep-research#evidence-assignment-the-heart-of-reduced-rag) 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:

```mermaid
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:

```text
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](/blog/lucidresume-evidence-filler), 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."](https://doi.org/10.1080/13594320902903613) *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."](https://doi.org/10.1257/aer.20181714) *American Economic Review*, 109(11), 3713-3744.
* Piopiunik, M., Schwerdt, G., Simon, L. and Woessmann, L. (2020). ["Skills, signals, and employability: An experimental investigation."](https://doi.org/10.1016/j.euroecorev.2020.103374) *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?"](https://doi.org/10.3389/fsoc.2024.1222850) *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."](https://doi.org/10.1111/ijsa.70022) *International Journal of Selection and Assessment*, 33(3).
* National Library of Medicine. [Journal Article Tag Suite (JATS).](https://jats.nlm.nih.gov/)
* Wang, X. [OpenResume: Open-source résumé builder and parser.](https://github.com/xitanggg/open-resume)
