Inline comments rot. They drift away from the code they describe, get half-updated in rebases, and end up actively lying to the next person who reads the file. The rationale you wanted to preserve — why this branch exists, what you tried before, which ticket this maps to — was never really about the code. It was about the decision.

Comments answer the wrong question

A good comment explains why. The problem: the “why” is usually a story, and stories don’t belong wedged between two lines of TypeScript. They belong somewhere a human will actually go looking when they’re confused.

That somewhere is almost never the file.

Quacks are persistent rationale

A quack is a short, timestamped narration of a decision, attached to the commit and the file range it touched. When a future engineer hovers the line, they see your reasoning — not as a stale comment, but as a thread they can reply to.

$ quack add src/billing/proration.ts:88-104
> We round half-up here because Stripe rounds half-even and
> we were getting 1-cent reconciliation diffs every Tuesday.
> See QS-441.

What to delete tomorrow

  • // TODO: fix this later — replace with a real ticket and a quack.
  • // HACK, // XXX, // NOTE: — all rationale, none of it durable.
  • Block comments that restate the function signature — your IDE already does that.

What to keep

Keep comments that explain what the code does when the code itself can’t — regex breakdowns, bitfield layouts, the load-bearing semicolon in an ASI footgun. Those earn their keep. Everything else is a quack waiting to happen.