Chapter 4 of 7. Prerequisite: You can't prompt your way to voice from the companion course. That chapter proved a prompt cannot hold a register. This one builds the drafting prompt anyway, because inside a pipeline the prompt still decides how far from your voice every draft starts.
The complaint is nearly universal and it is measurable. In the Write that blog! survey of developers who blog (Cynthia Dunlop, n=181), only 13% of those using LLM writing reported that the generated drafts sound like them. On the same page, 59% described the outputs as "generic AI" and 28% as a reasonable human writer who is nonetheless not them. The model writes competent prose. It writes somebody else's competent prose. If your pipeline drafts articles from your devlog, as the one in this course does, that gap is the difference between publishing your work and publishing a press release about your work.
This chapter is the drafting-prompt half of the answer. The enforcement half, the deterministic audit that counts what the prompt cannot hold, lives in the companion course's final chapter. Neither half works alone.
LLM voice consistency on a personal developer blog
Start from the prerequisite's conclusion: voice is enforced outside the model or not at all. A register is a property of the whole piece, and the model produces the next sentence from context. No instruction survives at whole-piece scope. So what is the prompt for?
Distance. A drafting prompt decides where in the space of possible prose the draft starts. Start it near your voice and the edit is a trim. Start it at the model's default register and the edit is a rewrite, and rewrites at that depth fail in practice because the editor gives up and ships the model's register with their name on it. The survey reports the 13% figure without offering a mechanism; this course's reading of it is that the default starting point is the centre of the model's training distribution, and nobody lives there.
The pipeline this course documents moves the starting point with three inputs, and none of them is an adjective:
- A locked thesis. The gate's drafting step runs from an agreed thesis only. The argument was evaluated bare, before any prose existed to make it feel defensible.
- Your source material. Devlog entries as evidence, with an explicit instruction to quote the source rather than paraphrase it.
- A voice profile. A short codification of your actual habits, stated as positive constraints.
The prompt may also carry one or two of your own published pieces as samples of the rules in practice: still your material, never somebody else's, and the profile documents the precedence explicitly, rules first, samples as illustration. Beyond that, everything the model might use to guess a register is deliberately absent. No "write in a conversational yet authoritative tone". No sample of somebody else's blog held up as the target. The rest of this chapter takes the three inputs in turn.
Prompt with your material, not with adjectives
The instinct when a draft sounds wrong is to describe the voice you wanted:
EXAMPLE — adjective prompting (do not send this):
Write this in my style: conversational but authoritative, technically deep
yet accessible, with a dry sense of humour. Avoid sounding like AI.
The prerequisite chapter documented what instructions like these execute as: surface markers at a density no human produces. Ask for warmth and you get warmth vocabulary. Ask for authority and you get a rate sheet. The adjectives are requests about the whole piece, and the model can only honour them one sentence at a time.
Material behaves differently. The drafting step in this pipeline hands the model the devlog entries behind the thesis, verbatim, and instructs it to quote them. A devlog entry already carries your register: your abbreviations, the way you name a bug, the numbers you bothered to record. When the draft is required to build around quoted source, large stretches of the piece are your prose by construction, and the model's connective tissue has your sentences on both sides to match. The same principle holds for anyone adapting this pattern without a devlog: feed the draft your commit messages, your incident notes, your half-written README paragraphs. The worst input you can give a drafter is a topic and a tone.
The thesis matters for the same reason. The pipeline's design notes are blunt about why prose is withheld until the argument is agreed: LLMs draft confidently, and a finished draft feels defensible even when its thesis is wrong. A drafter given a locked thesis and quoted evidence has two fewer dimensions to hallucinate in. What remains is the voice work, and that is where the profile comes in.
A voice profile is a positive constraint
The voice profile in this system started as a hand-written codification: ten short headed rules the author wrote directly about his own prose, bypassing a longer empirical enrolment process that was planned but not yet built. Each rule sits under a bold heading and states a habit in one to three direct sentences. The headings name the habits themselves: register, sentence structure, hedging, positivity markers, em-dash use, scope discipline, trade-off acknowledgement, lists, questions, meta-commentary. One rule in full: "Hedging. Near-zero. Opinions stated as opinions, facts as facts." That is the whole rule. No mechanism field, no threshold, no fix, because the profile is not a tells catalogue. The companion course's style guide keeps that separate artefact, a catalogue of generated-prose tells, and recommends a four-field shape for each of its entries: the pattern, the mechanism that makes it read as generated, the threshold where one exists, and the fix. The profile says what your prose does. The catalogue says what generated prose does. Keep them apart.
The important design choice is polarity. A profile that only bans things ("no em-dashes, no hedging, no rule-of-three") gives the model a hole where the register should be, and the model fills holes with its default. This pipeline's rewrite layer applies the profile as a positive constraint instead of bare deletion: when a flagged sentence is rewritten, it is rewritten toward the profile's stated habits: short declaratives, near-zero hedging, approval implied by proceeding rather than announced. Subtraction removes the tell. The positive constraint says what goes in its place.
At runtime the profile sits inside a two-layer stack, and the layers stay independent on purpose. The lower layer is a pure regex dictionary: no model, no network call. It flags hedging, performative warmth and padding, and it cannot rewrite anything, because a regex cannot preserve meaning. The upper layer is a rewrite agent that takes exactly what the regex flagged and reworks those spans through the profile. The scrubber runs without the agent. The agent consumes the scrubber's output but does not require it. The rewrite agent also runs on the same small, project-owned agent harness the pipeline's thesis generator uses; the rewrite layer arriving as a second consumer, using the harness unmodified, is what validated that harness's reusability claim.
One rule of scope keeps the whole stack honest. The rewrite agent touches flagged spans only. Whole-draft regeneration through a voice profile is adjective prompting with extra steps: it re-rolls every sentence, including the ones that were already yours.
The blind test both "improvements" failed
Every claim above would be worthless if voice-prompt changes were shipped on feel. The gate that keeps them honest is a blind A/B, and the incident that proved its value is documented in the post-mortem on this site.
The setting: a production voice skill driving drafts for a UK personal-finance calculator site. The original, v1.0.0, was working for single-page pieces. Two iterations tried to improve it at the prompt level before the pipeline scaled up.
v2.0.0 pushed analytical precision, on the assumption that UK finance readers want authority over warmth. Its Cash ISA draft came out, in the post-mortem's words, as "a rate sheet. Accurate, complete, cold." The register had shifted from useful guide to technical specification.
v2.1.0 corrected with framing cues to acknowledge the reader's decision context. The model complied literally and produced named empathy:
EXAMPLE — v2.1.0 output opener (the overcorrection):
Whether you're opening your first Cash ISA or reviewing an existing one…
The post-mortem's verdict on that opener: "The reader who wanted the rate has already scrolled past."
Then the test. Three Cash ISA drafts, same calculator, same data, same structure, version labels stripped before reading. The selection criterion was a single question: which draft would you publish on a live page? The selection came back v1.0.0. The original. Twice, across two rounds, test id SC-010.
The distinction the incident sharpened is the one to carry:
Iterative review asks whether the new version is better than the last. A blind A/B asks whether the current output is good at all. The first lets relative progress mask absolute regression. The second doesn't.
Both iterations had felt like progress from inside the loop. Both assumptions had felt reasonable during development. Neither survived contact with an unlabelled comparison that included the original.
The ship decision matters as much as the test. What shipped was v1.1.0: a reset, labelled as one, restoring v1.0.0 behaviour and adding exactly one thing. A rule, written into the skill's own versioning convention: if the blind test fails twice on the same voice change, reset to the last passing version. No third iteration. The entire v1.1.0 diff is that rule. A revert would have undone the mistake silently; the reset left the recovery path on record where the next iteration attempt will find it.
Split the work: what the prompt holds, what the gate holds
The last design decision is a boundary. Some voice rules are countable. The style guide behind this pipeline caps em-dashes at 3 per 1,000 words at article scope. A prompt cannot hold that rule, because the model does not track running totals while it drafts, and this system has the scar to prove it: a density check that ran per paragraph instead of per article passed a 14-em-dash piece at one per paragraph, and three articles with clean sidecars shipped over budget in a single day before the check was rewritten to article scope. The companion course's audit chapter covers that incident and the deterministic counter that closed it.
The boundary falls out cleanly once you stop asking the prompt to do the gate's job:
| Rule type | Where it lives | Why |
|---|---|---|
| Countable at article scope (density budgets, banned tokens) | Deterministic post-draft counter | The model cannot measure it while drafting; a program can, exactly |
| Local and executable (quote the source, open on the incident, name real numbers) | The drafting prompt | The model can honour it sentence by sentence |
| Register (does it sound like you) | Human edit on every manually gated draft; a bounded veto window on the automated path (next chapter); blind A/B on voice changes, the rule this system adopted after SC-010 | Whole-piece property; only a whole-piece reader holds it |
A prompt instruction that belongs in row one is a proxy waiting to fail. A counter that tries to measure row three is a proxy of the other kind: this system's own proxy incidents, covered in chapter 2 of this course, show gates getting satisfied while the rule they stand for is violated. And row three is only as strong as the reader it gets: chapter 2's incident had three drafts clear the automated path's review email with register problems caught only on the live site. Put each rule where it can actually be enforced, size the human checkpoint honestly, and every layer gets simpler.
The pattern, end to end
- Codify your voice from your own archive
Write the headed rules yourself, from your published posts and raw notes: one heading per habit, one to three sentences stating the habit directly. Keep it short; ten rules is the lived data point here. Label it a hypothesis in the file, because that is what it is until tested.
- Lock the thesis before any prose exists
One agreed argument per article, evaluated bare. A drafter with a locked thesis cannot spend fluency defending the wrong premise.
- Feed the drafter your material, verbatim
Devlog entries, commit messages, incident notes, with an instruction to quote rather than paraphrase. Your quoted prose anchors the register from inside the draft. Send zero adjectives about tone.
- Scrub deterministically, rewrite narrowly
A no-model pattern layer flags the tells. A rewrite pass reworks only the flagged spans, through the profile's positive constraints. Sentences that were already yours stay untouched.
- Blind-test every voice change, with the original in the pool
Strip the labels. Ask whether the output is good, never whether it improved. SC-010 caught two regressions that iterative review had approved.
- Name the reset rule before you need it
Two blind-test failures on the same voice change trigger a reset to the last passing version, recorded as a version of its own. Iteration without a reset path is how a guide becomes a rate sheet.
Notice how little of the pattern is prompt engineering. One step out of six touches the drafting prompt, and its content is source material plus a profile you wrote by hand. The production answer to "make the model sound like me" turned out to be an archive, a counter, a test and a rule. The prompt carries your evidence to the model. Your voice never left your side of the pipeline.
The next chapter goes to the other side of that boundary: the human checkpoints wired into the automated path, what happened when a live run exposed the wiring that was missing, and why a kill-switch with a deadline beats an approval queue.
Codify your voice and blind-test it
Write your own voice profile from your own archive and put it under a blind gate. Read your published posts and raw notes, then codify around ten headed rules, each stating a habit in one to three direct sentences as a positive constraint. Wire the profile into your drafting flow alongside verbatim source material, then run a blind comparison: several drafts of the same piece, labels stripped, judged on the single question of which one you would publish.
Expected behaviour
- A voice profile file exists with headed rules drawn from your own published prose, labelled as a hypothesis
- Rules state habits positively, saying what replaces a tell rather than only banning patterns
- A draft produced from the profile plus quoted source material sits alongside one produced from a topic and a tone, for comparison
- A blind selection round has been run with labels stripped and the outcome recorded, including which version won
- A reset rule is written down: what happens after two blind failures on the same voice change
PROVE IT Show the recorded outcome of your blind round and state which version you would publish. If the answer is your unmodified original, say so in the record; shipping the original is a legitimate result the gate exists to catch.
What question does a blind A/B answer that iterative review cannot?
How many headed rules does the hand-written voice profile in this pipeline contain?
Why does a profile that only bans things fail, and what does the positive-constraint version do instead?
Show answer
A ban-only profile leaves a hole where the register should be, and the model fills holes with its default, the centre of its training distribution. The positive constraint states the habit that replaces the tell, so a flagged sentence is rewritten toward the profile's stated habits: short declaratives, near-zero hedging, approval implied by proceeding. Subtraction removes the tell; the constraint supplies what goes in its place.
↺ re-read: “A voice profile is a positive constraint”