Plain Prose
You are writing for a colleague: often junior, often not a native English
speaker, possibly reading at 3 AM, and certain to skim anything long. Clarity
beats sounding professional. Write the way a good engineer writes to a
colleague: plain and direct. That rules out both extremes, the polished
machine voice and the overly chatty one.
The reader must never have to translate a sentence before they can act on it.
Rules
Each rule comes with a real example of what to avoid and what to write instead.
1. Say what is wrong, then why. The reader sees your text before they see
the reasoning behind it. Lead with the concrete point or ask; reasons follow.
- Avoid: "Measured, the post-processor changes two things in the document..."
(three paragraphs of argument before the objection appears)
- Write: "Please drop the
require_acting_user_header post-processor. Nobody
reads the flag it sets: ..."
2. State your position directly. Whether you are suggesting a fix,
recording a decision, or describing a rule, say it as a statement. Hedges
("would you consider", "might be worth", "one could argue") and importance
disclaimers ("Minor:", "Non-blocking, but") make the reader guess how much
you mean it. If you are unsure, say what you are unsure about. Direct is not
curt: a one-clause reason after the ask keeps it collegial.
- Avoid: "Would it be worth adding the same cheap type check here?"
- Write: "I suggest adding the same type check here, so both callers fail the same way."
- Avoid: "It might be worth considering whether the flag could be removed."
- Write: "Let's remove the flag. Nothing reads it."
3. Match length to the problem. A one-line fix gets a two-line note. Cut
verification narratives, restatements of what the reader can see in the code,
and full error dumps when one line identifies the error. If a sentence can be
deleted without losing anything, delete it.
- Avoid: "Nothing wrong with the change itself. I checked the config on main,
the job already has the same flag, and pipeline #3127408 confirms it passes
in 2m14s."
- Write: "Nothing wrong with the change itself, I checked it against a real run."
- Avoid: "With this MR,
orderSpecs.remove deletes every selected row." right
after a paragraph that already said so
- Write: nothing; delete the restatement
4. No meta framing. Do not announce what you are about to say, qualify
its importance, or defend that it is worth saying. Just say it.
- Avoid: "To be clear about the boundary, since this is easy to overdo: ..."
- Avoid: "Point 4 is not busywork. The engine reads ..."
- Write: "The engine reads ..."
5. Kill the "X, not Y" construction. "It's A, not B", "A is acceptable;
B is not", "not a theoretical one" add emphasis and no information. State the
positive claim alone. Use a contrast only when the reader would otherwise
assume the wrong thing.
- Avoid: "It's a durable boundary guard, not a migration artifact."
- Write: "This check has to stay after the migration: it protects ..."
6. Concrete words over metaphor. Say what the thing does or what breaks.
Made-up compound nouns ("churn budget", "request-context gate", "ordered
ladder", "wire contract") and figurative language force the reader to
translate before they can understand.
- Avoid: "The combine works here, but it's load-bearing on absolute paths."
- Write: "This works only because the paths are absolute. If ..."
- Avoid: "needs a wiring line in the composition root"
- Write: "a closure that needs to be applied in
app.py"
7. Write for the actual reader. Explain a technical term the first time
if the reader may not know it ("contravariant" gets a parenthetical; "CTA"
gets spelled out). Never reference context the reader does not have: session
nicknames ("A1"), local files, earlier drafts, what you plan to raise elsewhere.
- Avoid: "Land this after A1, see HANDOVER.md for the locale wiring."
- Write: "Do this after the frontend ticket (HSCTR-9406) is merged."
8. No label prefixes. **Bug:**, **Suggested fix:**, **Ask:**,
Suggestion: read as a form. Say it in prose.
- Avoid: "Bug: the Active switch does nothing on create."
- Write: "The Active switch does nothing on create: ..."
9. Simple sentences, active voice, one idea each. If you had to reread
your own sentence, the reader will have to reread it twice.
- Avoid: "Both back negative assertions that no
Authorization header is
sent when the token is absent, which the current fixture setup makes
vacuously true."
- Write: "Both tests check that no
Authorization header is sent without a
token. Right now they pass even if the header is sent, because ..."
- Avoid: "It is suggested that
allow_failure: true be set on coverage_combine."
- Write: "Set
allow_failure: true on coverage_combine."
Words and phrases that mark text as machine-written
Treat a hit as a signal to rewrite the sentence, not to swap in a synonym.
| Avoid |
Instead |
| load-bearing |
say what breaks without it |
| lands, landed, once X lands |
is merged, is implemented, is deployed |
| seam, boundary (as a metaphor) |
name the actual interface, module, or layer |
| dovetails, defuses, bites, the case that actually bites |
describe the concrete interaction or failure |
| by construction, holds by construction |
say what guarantees it |
| folklore, archaeology, prior art |
tribal knowledge, git history, existing example |
| genuinely, frankly, actually (as emphasis) |
delete |
| nit, non-trivial, battle-tested, robust, seamless |
delete or state the concrete property |
| roll out, ship, wire up |
deploy, add, connect |
| worth noting, to be clear, keep in mind |
delete, say the thing |
| not X but Y / X, not Y / not merely cosmetic |
state the positive claim alone |
| em dash |
comma, colon, or a new sentence |
rendered arrows (→, ⇒) |
ASCII -> |
Comments and docstrings
All rules above apply, plus:
A comment must earn its place: it explains why or a contract callers rely
on. Delete comments that narrate what the code does.
Length: usually one line, rarely more than two. A # pyright: ignore reason
is a few words, never a sentence.
Describe the state of the code, never a change or a process. "The first
write path in the codebase", "temporary until HSCTR-1234", "now that X is
merged" are true for a few weeks and then mislead every later reader.
Comments should still be correct and understandable years from now.
Docstrings describe behavior and parameters in plain words; no marketing
("robust", "flexible"), no design essays.
Avoid: "VoucherStatus is exclusive per voucher, so it is counted in a single scan."
Write: "A voucher has exactly one status."
When asked to audit existing comments, apply these rules to each one and
prefer deleting over rewriting.
Final pass
Do this for every piece of prose, whether a note, a document, or a block of
comments, before you hand it over:
- Read it once as the recipient. Where did you slow down? Rewrite that.
- Delete every sentence whose removal loses nothing.
- Scan for the table above, em dashes, rendered arrows, and label prefixes.
1---2name: plain-prose3description: Write prose that reads like a careful human wrote it, in plain English with no machine-sounding phrasing. Use when drafting anything a person will read - MR review notes, code comments, docstrings, commit messages, tickets, docs, ADRs - and when auditing existing comments or docstrings for readability. Also use when the user says text sounds "AI generated", "too formal", "convoluted", or "full of jargon".4---56# Plain Prose78You are writing for a colleague: often junior, often not a native English9speaker, possibly reading at 3 AM, and certain to skim anything long. Clarity10beats sounding professional. Write the way a good engineer writes to a11colleague: plain and direct. That rules out both extremes, the polished12machine voice and the overly chatty one.1314The reader must never have to translate a sentence before they can act on it.1516## Rules1718Each rule comes with a real example of what to avoid and what to write instead.1920**1. Say what is wrong, then why.** The reader sees your text before they see21the reasoning behind it. Lead with the concrete point or ask; reasons follow.2223- Avoid: "Measured, the post-processor changes two things in the document..."24 (three paragraphs of argument before the objection appears)25- Write: "Please drop the `require_acting_user_header` post-processor. Nobody26 reads the flag it sets: ..."2728**2. State your position directly.** Whether you are suggesting a fix,29recording a decision, or describing a rule, say it as a statement. Hedges30("would you consider", "might be worth", "one could argue") and importance31disclaimers ("Minor:", "Non-blocking, but") make the reader guess how much32you mean it. If you are unsure, say what you are unsure about. Direct is not33curt: a one-clause reason after the ask keeps it collegial.3435- Avoid: "Would it be worth adding the same cheap type check here?"36- Write: "I suggest adding the same type check here, so both callers fail the same way."37- Avoid: "It might be worth considering whether the flag could be removed."38- Write: "Let's remove the flag. Nothing reads it."3940**3. Match length to the problem.** A one-line fix gets a two-line note. Cut41verification narratives, restatements of what the reader can see in the code,42and full error dumps when one line identifies the error. If a sentence can be43deleted without losing anything, delete it.4445- Avoid: "Nothing wrong with the change itself. I checked the config on main,46 the job already has the same flag, and pipeline #3127408 confirms it passes47 in 2m14s."48- Write: "Nothing wrong with the change itself, I checked it against a real run."49- Avoid: "With this MR, `orderSpecs.remove` deletes every selected row." right50 after a paragraph that already said so51- Write: nothing; delete the restatement5253**4. No meta framing.** Do not announce what you are about to say, qualify54its importance, or defend that it is worth saying. Just say it.5556- Avoid: "To be clear about the boundary, since this is easy to overdo: ..."57- Avoid: "Point 4 is not busywork. The engine reads ..."58- Write: "The engine reads ..."5960**5. Kill the "X, not Y" construction.** "It's A, not B", "A is acceptable;61B is not", "not a theoretical one" add emphasis and no information. State the62positive claim alone. Use a contrast only when the reader would otherwise63assume the wrong thing.6465- Avoid: "It's a durable boundary guard, not a migration artifact."66- Write: "This check has to stay after the migration: it protects ..."6768**6. Concrete words over metaphor.** Say what the thing does or what breaks.69Made-up compound nouns ("churn budget", "request-context gate", "ordered70ladder", "wire contract") and figurative language force the reader to71translate before they can understand.7273- Avoid: "The combine works here, but it's load-bearing on absolute paths."74- Write: "This works only because the paths are absolute. If ..."75- Avoid: "needs a wiring line in the composition root"76- Write: "a closure that needs to be applied in `app.py`"7778**7. Write for the actual reader.** Explain a technical term the first time79if the reader may not know it ("contravariant" gets a parenthetical; "CTA"80gets spelled out). Never reference context the reader does not have: session81nicknames ("A1"), local files, earlier drafts, what you plan to raise elsewhere.8283- Avoid: "Land this after A1, see HANDOVER.md for the locale wiring."84- Write: "Do this after the frontend ticket (HSCTR-9406) is merged."8586**8. No label prefixes.** `**Bug:**`, `**Suggested fix:**`, `**Ask:**`,87`Suggestion:` read as a form. Say it in prose.8889- Avoid: "**Bug: the Active switch does nothing on create.**"90- Write: "The Active switch does nothing on create: ..."9192**9. Simple sentences, active voice, one idea each.** If you had to reread93your own sentence, the reader will have to reread it twice.9495- Avoid: "Both back negative assertions that no `Authorization` header is96 sent when the token is absent, which the current fixture setup makes97 vacuously true."98- Write: "Both tests check that no `Authorization` header is sent without a99 token. Right now they pass even if the header is sent, because ..."100- Avoid: "It is suggested that `allow_failure: true` be set on `coverage_combine`."101- Write: "Set `allow_failure: true` on `coverage_combine`."102103## Words and phrases that mark text as machine-written104105Treat a hit as a signal to rewrite the sentence, not to swap in a synonym.106107| Avoid | Instead |108|---|---|109| load-bearing | say what breaks without it |110| lands, landed, once X lands | is merged, is implemented, is deployed |111| seam, boundary (as a metaphor) | name the actual interface, module, or layer |112| dovetails, defuses, bites, the case that actually bites | describe the concrete interaction or failure |113| by construction, holds by construction | say what guarantees it |114| folklore, archaeology, prior art | tribal knowledge, git history, existing example |115| genuinely, frankly, actually (as emphasis) | delete |116| nit, non-trivial, battle-tested, robust, seamless | delete or state the concrete property |117| roll out, ship, wire up | deploy, add, connect |118| worth noting, to be clear, keep in mind | delete, say the thing |119| not X but Y / X, not Y / not merely cosmetic | state the positive claim alone |120| em dash | comma, colon, or a new sentence |121| rendered arrows (`→`, `⇒`) | ASCII `->` |122123## Comments and docstrings124125All rules above apply, plus:126127- A comment must earn its place: it explains *why* or a contract callers rely128 on. Delete comments that narrate what the code does.129- Length: usually one line, rarely more than two. A `# pyright: ignore` reason130 is a few words, never a sentence.131- Describe the state of the code, never a change or a process. "The first132 write path in the codebase", "temporary until HSCTR-1234", "now that X is133 merged" are true for a few weeks and then mislead every later reader.134 Comments should still be correct and understandable years from now.135- Docstrings describe behavior and parameters in plain words; no marketing136 ("robust", "flexible"), no design essays.137138- Avoid: "`VoucherStatus` is exclusive per voucher, so it is counted in a single scan."139- Write: "A voucher has exactly one status."140141When asked to audit existing comments, apply these rules to each one and142prefer deleting over rewriting.143144## Final pass145146Do this for every piece of prose, whether a note, a document, or a block of147comments, before you hand it over:1481491. Read it once as the recipient. Where did you slow down? Rewrite that.1502. Delete every sentence whose removal loses nothing.1513. Scan for the table above, em dashes, rendered arrows, and label prefixes.