Russell W. Hild · provenance demo
Designing a system that will not state what it cannot prove.
A generator writes job application documents, traces every claim to the record behind it, and blocks the ones that have none. The subject is a job search; the problem is not.
- subject
- job application documents
- method
- every claim graded by the record behind it
- data
- generated — no real person, employer or posting
- source
- github.com/ConsultRuss/provenance
The four labels
Every claim carries one letter.
- a — said directly by the subject, in a recording or a written answer.
- b — confirmed against a record independent of the subject.
- c — asserted by a tool and never confirmed.
- d — found only in a document this pipeline produced earlier.
Labels a and b ship; c and d do not. A claim labelled c or d cites no record, because there is nothing to cite — which is why a blocked claim has no wire on its left.
Where the evidence comes from
The left column is the subject's own record library: an intake interview, a work order export, a training record, a licence record, performance reviews. Each record is tagged with what kind of evidence it is, and that tag decides which label a claim resting on it can carry.
- self-report — the subject said it. Supports label a only.
- third-party record — someone else attested to it. Supports label b.
- system export — a system they operate produced it. Supports label b.
The two cannot be set independently. A claim labelled b citing only an interview would make the subject their own witness, so npm run seed refuses to emit it.
Why a derived document cannot be a source
A résumé is not evidence. Neither is a bio, a summary, or an earlier draft — those are outputs. If a claim's only backing is a document this pipeline wrote, it is circular: the system is citing itself. Label d marks that case. The fix is to find the record the first document should have cited, or to drop the claim.
The gates
Six gates, in order. Each rejects something specific.
- intake — postings with no verbatim requirement text to quote.
- live check — postings that closed or went stale since intake.
- pressure test — applications where a must-have requirement lands on do not have.
- wildcard question — applications with no honest answer to the posting's open question.
- asset lint — documents containing a claim labelled c or d.
- submitted — nothing. Reaching it means every check cleared.
A record stops at the first gate that rejects it. Most records stop.
The export
The download button writes a PDF of the document on screen. Blocked claims are not in it — each is replaced by a line saying a claim was withheld for want of a record. Every claim that ships carries a footnote naming the file it came from, so it keeps its provenance off the page.
The data
Everything here is generated. npm run seed writes every record, requirement, document and gate result from a fixed seed, and the same seed always produces the same files. No real company, person, posting or transcript enters this repository, and the names are invented.
Numbers are not round, because measured counts rarely are. The output always contains blocked claims and unanswered requirements — a clean run would prove nothing.
At a glance
This page demonstrates grounding and refusal in a generated-document pipeline. Every factual claim carries the record it came from and a label grading how well that record supports it. Claims with no record are blocked before they reach a document, and blocking is the ordinary outcome rather than an error.
The four evidence labels
- a — the subject said it — supported by a self-report, ships
- b — a record confirms it — supported by a third-party record or a system export, ships
- c — claimed, never checked — no record, blocked
- d — only in an earlier draft — traced to a document the pipeline itself wrote, blocked
Labels a and b ship. Labels c and d cannot, and a claim carrying either is required to cite the null record. The label and the record are one decision, not two: a self-report can only ever support label a, so a claim cannot be graded higher than the evidence behind it.
What the run produced
- 47 claims parsed across 14 application records.
- 41 claims cleared. 6 were blocked for want of a record.
- 23 distinct records in the candidate's library, across three kinds: self-report, third-party record, and system export.
- 11 of 14 applications were refused. 3 were submitted.
The six gates
- intake — Reads the posting and pulls out what it asks for, word for word. Stopped 2.
- live check — Checks the job is still open before any work goes into it. Stopped 2.
- pressure test — Asks honestly whether this person can do the job, requirement by requirement. Stopped 2.
- wildcard question — Works out an honest answer to the odd question the posting asks. Stopped 1.
- asset lint — Reads the finished documents and checks every claim has a record behind it. Stopped 4.
- submitted — The application goes out. Stopped 0.
The pressure test
Each requirement is given a verdict before any document is written. The overall call is derived from the rows, so it cannot flatter them.
- Field diagnostic experience (must) — have as documented.
- Manufacturer service training (must) — have as documented.
- Crane and rigging certification (preferred) — do not have.
- Commercial driver licence (preferred) — have as documented.
- Crew leadership (must) — adjacent but honest.
The finding
The cover letter makes two claims no record supports, and answers 3 of 5 requirements. The résumé states the smaller, true version of one of those claims and answers 4 of 5. The padded document scores worse than the honest one. Exporting the cover letter to PDF omits the unsupported claims entirely and prints a withheld notice in their place.
In machine-learning terms
This is grounding and citation with refusal — abstention — as the default when evidence is absent. Provenance is enforced in the schema rather than by a filter applied afterwards, which is what makes hallucinated or unsupported output unrepresentable rather than merely unlikely. The invariants are executable: the generator throws rather than emit a claim whose label and record disagree, and a check fails the build if one ever appears.
Demo data. The candidate, employer and posting are invented; every figure
above is produced by npm run seed from a fixed seed in this repository.