@@ -512,6 +512,89 @@ When stuck in debugging loops:
5125123. **Document the issue** comprehensively for a fresh approach
5135134. Format for portability (using quadruple backticks)
514514
515+ # # Comments earn their maintenance cost
516+
517+ A comment ships only if it passes all three gates. Fail any : delete or rewrite.
518+ Borderline : delete — borderline means the information is reconstructible, which
519+ is what makes deletion cheap.
520+
521+ **Loss.** Three years from now, would losing this cost a maintainer real time
522+ rediscovering intent, an invariant, a constraint, or a failure mode the code and
523+ tests do not already make obvious?
524+
525+ **Elite.** Would SQLite, Redis, the Go standard library, or CPython write this
526+ comment, at this length? Those projects state the constraint and stop. They do
527+ not argue with an imagined objector.
528+
529+ **Upkeep.** Will it stay true without maintenance? A comment that hand-syncs a
530+ value the code owns — a count, an offset, a line reference, a duplicated
531+ constant — is false the first time that value moves.
532+
533+ # ## Ceiling
534+
535+ One or two lines. A comment reaching four is either carrying several facts, in
536+ which case split it, or arguing, in which case cut it to the fact.
537+
538+ Rationale, alternatives weighed, and the story of how the code got here belong
539+ in the commit message : timestamped, attached to the exact diff, and free to
540+ maintain.
541+
542+ A comment often holds both a constraint and the deliberation that found it. Keep
543+ the constraint, cut the deliberation. "Runs at most once per second" survives;
544+ " this is the right trade for now" does not.
545+
546+ # ## Keep
547+
548+ - Why over how : upstream quirks, protocol and compatibility constraints,
549+ performance tradeoffs still part of the contract.
550+ - Invariants, preconditions, ordering, lifetime, and concurrency requirements
551+ that types and tests cannot express.
552+ - Code that looks wrong but is not, so a later cleanup does not reintroduce the
553+ bug.
554+ - A high-level sketch of an algorithm whose local operations do not reveal the
555+ whole.
556+
557+ # ## Delete
558+
559+ - Narration of the next lines; code translated into English.
560+ - Restated names, types, defaults, or control flow.
561+ - Values duplicated from the code and hand-synced.
562+ - Justification, hedging, or apology for a choice.
563+ - Speculation about future requirements.
564+ - History version control already holds, including commented-out code.
565+ - Ticket and issue numbers. They say nothing to a reader without tracker access,
566+ and they rot when the tracker moves. Unfinished work goes in the tracker, not
567+ the source.
568+ - Transient observations — "currently", "for now", "the latest release" —
569+ that go stale with no nearby edit.
570+
571+ # ## The upkeep gate in practice
572+
573+ It reaches values that track our own code. It does not reach frozen external
574+ facts.
575+
576+ Bad (Delete) :
577+
578+ ` ` ` python
579+ # There are 321 tests to complete for servers.
580+ ` ` `
581+
582+ Good (Keep) :
583+
584+ ` ` ` python
585+ # CPython < 3.11 has no ExceptionGroup, so this branch stays.
586+ ` ` `
587+
588+ # ## Documentation exception
589+
590+ Doctests, minimal usage examples, and param, return, and raises lines on public
591+ API are exempt from the loss gate — they serve the caller, not the maintainer.
592+ They are exempt from nothing else. Ceiling : a good man page entry.
593+
594+ NumPy-style `Parameters`, `Returns`, and `Attributes` sections and executable
595+ doctests fall under this exception — autodoc ships every field whether or not
596+ you describe it, and a doctest that runs is also a test.
597+
515598# # AI Slop Prevention
516599
517600Treat AI slop as **review-hostile noise**, not as proof that text or
@@ -569,8 +652,9 @@ on unrelated code while still resolving.
569652
570653# ## Preservation & Context
571654
572- **When unsure, leave the text in place and ask.** Subjective cleanup
573- must never be a reason to remove load-bearing rationale.
655+ Subjective cleanup must never remove load-bearing rationale. Adjudicate
656+ comments with the comment policy above; borderline cases are deleted, not
657+ kept.
574658
575659- **Preserve the "Why":** You MUST NOT delete comments that document
576660 invariants, protocol constraints, platform quirks, security
0 commit comments