The problem
A language model is a wonderful drafting tool and a terrible final authority. Ask one to tailor a CV and cover note to a role and it will write fluent prose, then quietly drift: it invents an employer, pads a date, reaches for an em dash, or lets a confidential project name slip into the page. The fix is not a sharper prompt, because the next run drifts somewhere else. The output is plausible every time and trustworthy none of the time.
What is missing is the same thing a type checker gives a dynamic language, or a load combination gives a structural design: a hard envelope the creative part cannot leave.
What I built
tailored is that envelope. A stochastic model proposes the prose; a chain of deterministic gates decides what ships. The model is free to be creative, but nothing reaches the document you send until it has cleared every gate, and each gate returns the same verdict on the same input.
tailored validate canon.yaml # schema: the facts are well formed
tailored lint cv.html cover.html # ai-tell: no em dashes, no machine tells
tailored page-fit out/cv.pdf --max 1
tailored ip-guard cv.html --canon canon.yaml- Schema gate. The candidate's facts live in a single
canon.yaml. If it is malformed, the run stops before a word is written. - AI-tell lint. No em dashes, no double-hyphen connectors, no smuggled em-dash entities: the tells that give machine writing away, caught by rule rather than by taste.
- Page-fit gate. The rendered PDF must fit its page budget, measured against the real document, not a guess.
- IP-guard. A
protectedTopicslist names terms that must never appear in any output, so confidential work cannot leak into a public pack. - Honest about the fifth. Whether a page actually looks right is a job for a human or an agent reading the preview, not a regular expression, and the tool says so rather than pretending to automate judgement.
Four of the five gates pass or fail with an exit code, so continuous integration and the skill that drives the loop can both gate on them. The candidate's private facts never leave the machine: canon.yaml is gitignored by default.
Outcome
It produces my own tailored CV and cover packs, and it underpins the thesis of this site: wrap the stochastic part in checks that fail the build, and generated output becomes something you can rely on. It is interlock's argument applied to documents instead of pull requests. Open source, with the gates shipped and tested rather than promised.
Tech
A small TypeScript toolkit with a tailored CLI, paired with a Claude Code skill that orchestrates the drafting loop and calls the gates. Rendering goes through headless Chrome; page counting and previews through poppler. The deterministic gates are tested and run the same way locally and in CI.