Methodology

The Comments Were a Symptom

28% comment-to-code across 1,505 files, one app at 115%, and getting worse. I nearly fixed it by deleting comments — which would have destroyed the only surviving copy of the reasoning.

Methodology6 min read

I — What the measurement said

I ran a comment-density pass over everything my agents had written. Not because anything was broken — the builds were green and the code worked. I was curious.

Across 1,505 hand-written source files:

  • 28% comment-to-code overall
  • 183 files carrying a header essay of 25 lines or more — 8,477 lines of them
  • worst app at 115% — more comment than code
  • one component at 227 lines, of which roughly 22 were code

And the trend was the part that actually bothered me: the two newest builds were the two worst. Whatever was causing it was not a legacy problem working its way out of the system. It was accelerating.

II — The fix I almost shipped

The obvious move is a rule. Comments should be short. A source comment says why in a line or two and links out. Narrative build history does not belong in a file header. Add an audit, fail the build on a wall of comment, delete the offenders.

I wrote most of that. Then I went to look at what I would be deleting, and it stopped me.

The headers were not padding. They were things like why a particular Critical from a code review got fixed one way and not the other, which alternative was tried and rejected, what got measured and what the number was. Real reasoning. The kind of thing that is genuinely expensive to reconstruct and that the shipped code does not state anywhere, because working code describes what it does and is silent about what it almost did instead.

III — Why the agents were doing it

This is the bit that reframed the whole thing for me.

I had been treating verbose headers as a style problem — agents being over-thorough, writing for an imagined reader, not knowing when to stop. If that had been the cause, a style rule would have fixed it.

It was not a style problem. It was structural.

The code-review reports and test reports were gitignored. They had been deliberately tiered out of version control as "superseded by the shipped code", which sounded right at the time and was wrong. So when an agent finished a review, worked out something worth keeping, and asked itself where that knowledge should live so it survives — the honest answer was nowhere. The report it was writing into would not survive a clone.

The only durable, clone-surviving surface available was the source file.

So the agents put it there. Every time. Reasonably. The behaviour I was about to punish with a lint rule was a correct response to a gap I had created, and the acceleration made sense too: the more the agents learned, the more there was to preserve, and the only place to preserve it was getting fatter.

IV — The actual fix

Both halves had to move together, and only one of them is the rule:

Give the knowledge a durable home, then cap the comment. Code-review and test reports are now tracked in git, and docs/build-decisions.md is the component-grained record — the destination a short source comment points at. Only then does the density rule mean anything.

Notice the order. Capping comments first would have been actively destructive. Tracking the reports first makes the cap safe, because now the comment has somewhere to point.

The cost is real and I accepted it knowingly: those reports are verbose, one per tranche, and they will accumulate. That is cheaper than the same prose living in .tsx files, where it bloats every file anyone opens and no gate can see it.

docs/build-decisions.md specifically — not docs/decisions.md, which is the ADR reader's index and gets regenerated wholesale on a heavy docs pass. I found that one the boring way: writing build decisions there means they are silently overwritten the next time documentation runs.

BEFORE
28%
comment-to-code
across 1,505 files
115%
worst app —
more comment than code
Ignored
where review reports
lived
Source
only clone-surviving
home for reasoning
AFTER
Capped
wall at 25 lines
fails the build
Tracked
review + test reports
in git
build-decisions
component-grained
record
Harvest
before deleting
any header

V — The general shape

I have started treating this as a diagnostic question rather than a one-off.

When an agent — or a person — does something consistently wrong in a way that looks like sloppiness, it is worth asking what would have to be true for the behaviour to be the best available option. Often something is, and it is usually a missing place to put something.

Verbose headers meant there was nowhere durable to write reasoning. If I saw duplicated constants everywhere, I would suspect there is no obvious module to own them. Defensive re-checking of the same value suggests nothing upstream guarantees it.

The tell is consistency. One agent writing an essay in a file header is a quirk. Every agent doing it, on every build, more over time, is a system telling you about itself. Sloppiness is random; this was not random, and I should have read that sooner than I did.

Rule 01

A source comment says why, briefly, and links out.

One or two lines. A single block over 10 lines is a smell and over 25 is a defect. Build history, review findings, task IDs and measurement logs belong in the product’s tracked decision record, not a file header.

Rule 02

Harvest before you delete.

Four of eight apps had no surviving review reports, so the header was the last copy. Never close a comment-density finding by removing the text — move it somewhere durable first, then trim.

Rule 03

Fix the structure before you write the rule.

Capping comments while the reports were still gitignored would have deleted knowledge and solved nothing. The reports had to become tracked first; only then does the cap have somewhere to redirect to.

Rule 04

Consistent “bad” behaviour is a system signal.

When every agent does the same wrong-looking thing, and does it more over time, it is usually the correct response to a missing affordance. Ask what would make it optimal — the answer names the gap.

VI — The takeaway

I set out to fix bloated comments and found out I had caused them. The agents were not being verbose; they were routing around a hole where a durable record should have been, and the file header was the only surface that survived a clone.

The rule I ended up with is nearly the one I started with — a comment says why, in a line or two, and links out. What changed is everything underneath it: the reports are tracked, there is a decision record at the right grain, and the audit that enforces the cap is mutation-tested so I know it can actually fail.

Whether this generalises perfectly I would not claim. But it has changed the first question I ask when something looks like carelessness, and so far that question has been worth more than the rule that came out of it.

The audit that enforces this is one of three that every tranche exits through — the reasoning behind treating them as real gates is in Do the Skills Earn Their Keep?.