Skip to content

Comments and prose

Everything else in this repository has something checking it. A wrong type fails the typecheck lane and a broken link fails the docs lane. A comment has nothing. It can contradict the line beneath it for a year while every lane stays green. So comments go stale first and get noticed last.

These rules are written for source files, and they carry over. A commit message, a documentation page and a pull request description reach the same stranger under the same handicap, since nothing checks those either. One mechanical difference exists: Markdown here is never hand-wrapped, and Code style names the setting that enforces it.

Because nothing checks it, the safest comment is the one nobody wrote. But two things are worth the risk anyway: a constraint the code cannot show, and a fact that must not get lost. The rest is noise, and the noise is not free, because a file thick with restatement teaches the reader to skim, and the one comment that mattered gets skimmed along with the rest.

  • Never retell the code. If the comment paraphrases the statement under it, delete the comment. The paraphrase goes wrong the moment the statement changes, and the next reader believes the paraphrase.
  • Never narrate a platform fact the line already carries. clearTimeout needs no note saying that it clears a timer. A reader who does not know that has documentation; a reader who does has been stopped for no reason.
  • Write a cross-cutting fact down once, in the module that owns it. Two copies drift and no tool reports the drift, so every other site links to that module or stays silent.

The reader is the only verifier a comment will ever get. Naming the source turns a claim taken on trust into one anybody can settle against library documentation, a standard, or this repository.

  • Say where a behaviour claim comes from. A comment reading isolated-vm kills the synchronous portion with the bare message Script execution timed out. sends the reader to a source they can open. The engine sometimes cuts execution short sends them nowhere, and a claim nobody can confirm is also a claim nobody can correct.
  • Keep internal process facts out. No session history, no decision minutes, no task or plan references, no reviewer names. Nobody outside the room where it happened can check any of it, and the room empties.
  • State a finding at the strength the evidence supports. One code path is an observation. Written as a law it will be read as one, and the first counter-example gets blamed on the code, not on the comment.

Being true is not enough. Facts earn a place by being the cause of what they describe, by surviving the next edit to that thing, and by changing what the reader does. Text assembled from every detail that happened to be true reads as thorough on the day it is written and comes apart one edit at a time afterwards.

  • Trace a fact back to what makes it true, and state that instead. The Node floor is the range the workspace declares in package.json, and an install underneath it fails outright. Version managers and the file they read stand on that range, so a text documenting them teaches a habit where a constraint belongs, and it goes stale the day somebody changes their habit.
  • Ask what happens when the next person deletes the thing tomorrow, changes it, or adds another beside it. Lint rules and formatter options are entries in files anybody can open. Listing one in prose makes a second copy of a fact, and no lane compares the two. The copy in prose goes wrong in silence, so name the file that carries the setting and let the reader open it.
  • Leave out what the reader cannot act on. Knowing a lint rule’s identifier does not change the code somebody writes, and the rule stated plainly is both shorter and still true after a rename.
  • Soften a claim instead of qualifying it into an enumeration. The absolute rescued by naming its one exception is exact today and wrong the moment a second exception appears, and the exception itself belongs wherever the rule it qualifies lives. One execution runs per worker by default, and a comment naming the single setting that raises the number goes stale the day a second one lands. Writing by default outlives both.

Write for the stranger who opens the file first

Section titled “Write for the stranger who opens the file first”

Assume the reader came in from a search result, knows nothing about the project, and will read this file and no other. That reader is not hypothetical. In a year it is you.

  • No fragment stands where a sentence belongs. A label with a colon after it, or a shorthand note to self, means whatever the reader decides it means. But a colon following a complete clause is ordinary punctuation, and it introduces the explanation or the enumeration that clause promised.
  • A comment states a constraint. It never defends a decision and never answers a reviewer: the argument that convinced the reviewer ended when the branch merged, and the constraint is the part that outlived it.
  • No parenthetical explanation appears anywhere: not in a name, not in a comment, not in documentation, not in a commit message. A parenthesis is where a writer puts the piece of a thought they declined to finish, so finish it and give it its own sentence. This rule has no exceptions.
  • The em dash and the en dash are out for the same reason. Each one brackets a qualifier the writer declined to give a clause of its own. A qualifier that earns its place becomes a sentence, but one that does not was never worth the mark.
  • No first person appears in any text. we and our name a group the reader was never in, and a year later they name nobody at all.
  • Write English throughout, in code, comments, documentation and commits. Decorative emoji stay out of all four.

The settings below hold across the tree, so that no file decides them again. Review is the only check on any of them, and each one shows up first as a page that reads as though a second author wrote it.

  • A heading is sentence case. Words that carry a capital of their own keep it, so a capital past the first word belongs to the word and not to the heading.
  • Quotation marks are straight. Curly marks come from an editor that substitutes them, and they break a copied command the moment somebody pastes it into a shell.
  • Emphasis is carried by the sentence and never by bold type. Bolded lead-ins are labels standing where a subject belongs, and on a page carrying several of them a reader learns to read the bold and skip the rest.

Each row is a shape to avoid, with one example of it. None of them looks like a problem on the line it sits on.

Anti-pattern Example to avoid
False absolute // V8 always releases the isolate on dispose.
Meta-commentary // This file was reworked to keep the parser small.
Flowery phrasing // A delicate dance between the host and the isolate.
Tacked-on speculation // Possibly related to how libuv batches timers.
Test cross-reference // See the "rejects after dispose" test for the details.
Label in place of a sentence // Why: the setter doubles as the completion signal.
Semicolon-chained fragments // Host side only; cleared in finally; never leaks.
Rhetorical justification // This is not over-engineering; the alternative would be far worse.
Code-structure narration // Walk the tree with an explicit stack instead of recursing.
Restated config entry // Forbidden by the no-underscore-dangle rule in the lint config.

The replacement is almost always smaller than the comment it replaces. A false absolute narrows to the claim the evidence supports. Speculation gets verified and stated as fact, or dropped. A test cross-reference becomes the behaviour itself, written where the behaviour lives, because a test name is not a stable address. A restated config entry becomes the rule the code has to follow, stated without the entry, because the file carrying the setting is the only copy anything checks. Structure narration becomes the reason the structure is required, or it is deleted, since the code already shows the structure to anyone reading it.

Put it through the audit. A no anywhere means it is not finished.

  1. Is every sentence whole, with no fragment and no note to self?
  2. Does it stand on its own for someone opening this file with no other context?
  3. Is every fact in it checkable from library documentation, a standard, or this repository?
  4. Does it state a constraint, without defending a decision or narrating the code?
  5. Does every fact in it name a cause the reader can act on, and not a detail that moves the next time somebody edits a tool?