Core rule: write comments when they encode information the code does not already make obvious. Do not write comments that merely restate the code.
- Invariants the code does not enforce structurally.
- Business rules, compliance rules, security review outcomes, data-retention rules, and payment or audit constraints.
- Non-local constraints that live in another file or service.
- Refactor-sensitive rationale next to code that looks simpler than it is.
AIDEV-NOTE:anchors for rules that must survive future agent edits.
- Comments that paraphrase the next line.
- Generic AI-style docstrings such as "Returns the appropriate value."
- Vague warnings without a named file, symbol, rule, or consequence.
- Historical notes that no longer affect the current code path.
Weak:
// There are processor considerations for gift-card refunds.Strong:
// AIDEV-NOTE: Gift-card refunds must cap at 24h regardless of any tier.
// The processor settles at T+1 and refunds beyond 24h are unrecoverable.Strong for non-local rules:
// AIDEV-NOTE: For gift-card refund caps, use capRefundWindow from
// processor_rules. Do not return raw window constants for gift-card orders.Some words decay faster than others because they imply precision the code does not enforce. When you reach for one of these, anchor it.
A user-facing API kept available for backward compatibility. The code path is current; only the name is historical.
Required annotation: replacement and earliest version it can be removed.
// AIDEV-NOTE: legacy-public - `oldName` kept for v1.x consumers.
// Replaced by `newName`. Earliest removal: v2.0.A code path used today as the fallback when a newer system has gaps. Not deprecated; the fallback is load-bearing.
Required annotation: what triggers the fallback, and what newer path replaces it once gaps close.
// AIDEV-NOTE: compat-fallback - used when ResolvedLayout.content is absent.
// Retire once pm-adapter populates content for every fragment.Code or a symbol that no longer exists in the repo. Should not appear in comments at all. Describe the change in the PR or git history. A comment naming a removed symbol as "context" is itself a candidate for removal.
Actively scheduled for removal.
Required annotation: replaceWith and either removeIn or
compat-indefinitely (with reason).
/** @deprecated replaceWith=`viewOptions.layout: 'web'` removeIn=v2.0 */A bare @deprecated is treated as incomplete: either annotate or delete.
A short-lived workaround.
Required annotation: condition for removal and an issue id.
// AIDEV-NOTE: temporary - disable until SD-1234 lands the new path.A temporary comment without an issue id is treated as permanent, which is
almost never what was intended.
In agent-heavy codebases, comments and docs are part of the prompt surface. A stale comment is not harmless decoration. It can become an instruction the next agent follows. If a comment no longer reflects the code, update it or delete it in the same change.
README.md, AGENTS.md, CLAUDE.md, architecture notes, runbooks, and
tutorials are prompt surface too. If a code change invalidates one of these
docs, update or delete the stale prose in the same change. A stale root
instruction can be more dangerous than a stale inline comment because agents
may treat it as project policy.
Treat the comment as a documented constraint. If the requested change appears to violate it, surface the conflict instead of silently choosing one side.
Use comments sparingly, but preserve and add them when they encode invariants
the code does not structurally enforce. Prefer specific `AIDEV-NOTE:` anchors
for business, security, compliance, and non-local rules. Do not add comments
that paraphrase code. When reaching for loaded terms like `legacy`,
`deprecated`, or `temporary`, follow the taxonomy in `comment-policy.md`.
Treat stale comments and stale agent-facing docs as bugs.