Source: [Self-documenting AI code: make intent survive the chat — Skills for Business](<https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/>)

[← All articles](https://skillsforbusiness.ai/blog/)

Development · Guide

# Self-documenting AI code: make intent survive the chat

Best practices for self-documentation in AI-assisted coding: clear names, useful contracts, verified rationale, executable examples and maintained repository docs.

[Skills for Business](https://skillsforbusiness.ai/blog/editorial/)31 October 20267 min read

On this page

1.  [Make the behavior visible before explaining it](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#make-the-behavior-visible-before-explaining-it)
2.  [Document contracts that names and types leave open](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#document-contracts-that-names-and-types-leave-open)
3.  [Preserve the reason without inventing a history](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#preserve-the-reason-without-inventing-a-history)
4.  [Treat generated comments as claims to check](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#treat-generated-comments-as-claims-to-check)
5.  [Put each explanation where its reader needs it](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#put-each-explanation-where-its-reader-needs-it)
6.  [Include documentation in the definition of a finished change](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#include-documentation-in-the-definition-of-a-finished-change)
7.  [Review from the next reader’s position](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#review-from-the-next-readers-position)
8.  [Sources](https://skillsforbusiness.ai/blog/self-documenting-ai-code-best-practices/#sources)

What to take away

-   Make behavior readable in code, and preserve non-obvious contracts and rationale beside the relevant interface or decision.
-   Check AI-generated explanations against implementation, tests and actual requirements; do not invent historical reasons.
-   Update setup instructions and examples with the change, keeping durable knowledge in the repository.

Good self-documentation in AI-assisted coding means that someone can understand, use and safely change the result after the conversation has disappeared. Start with clear code. Add precise interface contracts and the reasons that the implementation cannot explain on its own. Keep setup commands, operational instructions and consequential design decisions in maintained repository files.

AI can help draft all of these, but the explanation it produces needs review alongside the code. An assistant can describe a mistake convincingly or invent a reason for an unusual branch. Documentation becomes useful when it preserves verified knowledge and exposes unresolved assumptions.

This guide proposes a practical workflow for developers and engineering leads. Its access-window example is fictional. We have not run a study of developer comprehension or independently compared coding assistants for this article.

## Make the behavior visible before explaining it

Ask the coding assistant to use names from the business domain, make units explicit and keep related logic together. A reader should be able to distinguish a duration from a timestamp, a requested change from a confirmed one, and a predicate from an action with side effects.

Avoid adding layers solely to make the code look sophisticated. A small, direct function can explain a rule better than a generic framework with several configuration switches. Follow the repository’s existing conventions so readers can transfer what they already know.

[Google’s engineering review guidance](https://google.github.io/eng-practices/review/reviewer/looking-for.html) treats understandable complexity, naming, comments and documentation as related review concerns. It recommends simplifying unclear code and preserving rationale in useful comments. It also distinguishes implementation comments from documentation explaining how an interface should be used. This is practitioner guidance, not experimental proof that a naming style reduces AI coding errors.

Use that distinction when prompting: request a clear implementation first, then ask which important information remains unavailable to a reader. Repeating each statement in English adds text without necessarily adding understanding.

## Document contracts that names and types leave open

Consider this deliberately vague Python function:

```
def check(t, n):
    return n >= t
```

The comparison is easy to read. Its meaning is not: which argument is the observation time, what happens at equality, and what time conventions apply?

In a fictional application, access windows include their start instant and exclude their end instant. The following illustrative helper expresses only whether the window has ended:

```
from datetime import datetime

def has_access_window_ended(
    *,
    ends_at_utc: datetime,
    now_utc: datetime,
) -> bool:
    """True at or after the end instant.

    Inputs must be timezone-aware UTC.
    """
    return now_utc >= ends_at_utc
```

The function assumes those input preconditions have been checked at the application’s boundary; its names and type annotations do not enforce UTC. It also does not decide whether access has started or whether a user is authorized. That limited responsibility is part of making it understandable.

John Ousterhout’s [2018 Stanford notes on comments](https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/lecture.php?topic=comments) argue that code alone cannot cleanly communicate all design knowledge. His examples include units, boundary conditions, null meaning and the separation of interface from implementation documentation. These are useful questions for AI-generated code even when its syntax appears obvious.

For the fictional rule, retain an executable example at the exact end instant as well as examples just before and after it. Such examples make the agreed boundary visible and can detect an accidental change from `>=` to `>`. They do not establish that the whole access system is correct.

## Preserve the reason without inventing a history

An interface contract describes what callers can rely on. Rationale explains why a choice was made. In the example, an approved design note could explain that adjacent access windows must not both include the same boundary instant. Keep that reason near the rule or in a linked decision record if it spans several components.

Ask AI to locate the actual evidence for a rationale: a requirement, issue, design decision or established external contract. If it cannot find one, let it identify an assumption or ask for a decision. A comment such as “required for compatibility with older customers” is misleading when nobody has established that history.

Separate observed behavior from intended behavior. When existing code and the stated requirement disagree, document the discrepancy for resolution. Generating a docstring from the implementation can accurately describe what it currently does while preserving the wrong business rule.

Also review stale comments in the changed area. A new branch can make an older warning false, and a removed workaround can leave an obsolete explanation behind. Update the implementation and its explanation together so the next reader does not have to decide which one to trust.

## Treat generated comments as claims to check

The [December 2025 revision of Guelman and colleagues’ study](https://arxiv.org/html/2408.14007v3) evaluates generated Javadoc against curated comments and human assessments. It finds limits in how well text-similarity metrics capture those assessments. The study uses Java code elements and historical models, with target code supplied without surrounding project context; it does not establish the reliability of today’s repository-aware coding agents.

For a code review, the practical implication is to inspect the claims. Does a function documented as read-only write to a cache? Does a “returns an empty list” claim match a branch that raises an exception? Does the promised unit match what callers supply? A polished paragraph or a high similarity score cannot answer those questions on its own.

Check public contracts against relevant call sites and tests. Check rationale against its source. Keep uncertainty explicit when context is missing. Avoid accepting extra claims merely because the assistant added them while making the documentation sound complete.

## Put each explanation where its reader needs it

The [Diátaxis documentation framework](https://www.diataxis.fr/start-here/) separates learning tutorials, task-oriented how-to guides, technical reference and explanation. Its useful contribution here is the reader’s purpose: someone looking up a parameter needs a different document from someone trying to understand an architectural tradeoff.

The following placement guide is an editorial proposal for an ordinary repository. Adapt it to existing conventions rather than creating empty folders for every category.

| Information to preserve | Suitable home | What to avoid duplicating |
| --- | --- | --- |
| Local behavior and domain meaning | Names, types and focused functions | Line-by-line prose translating obvious statements |
| Inputs, outputs, errors and side effects | Interface docstring or API reference | Internal implementation detail callers do not need |
| Non-obvious decision and rejected alternative | Nearby rationale or a linked decision record | An invented explanation of past intent |
| Setup, verification and operational recovery | README or task-specific runbook | Commands copied into several competing guides |
| Instructions for future coding agents | Repository agent instructions linking canonical docs | A second, drifting copy of project architecture |

Keep a clear authoritative location for facts that change. For example, a short agent instruction can point to the maintained build guide instead of repeating its complete command sequence. That link does not guarantee that every assistant will read it; verify behavior in the actual workflow when it matters.

## Include documentation in the definition of a finished change

Give the assistant a bounded documentation task with the implementation request. A reusable prompt could be:

```
Read the relevant code, tests and project documentation first.
Implement the requested change using existing naming conventions.
Document non-obvious contracts and verified rationale near their users.
Update affected setup, API or operational instructions in their
canonical locations. Flag missing requirements; do not invent intent.
Report the checks actually run and any examples left unverified.
```

Review the diff for documentation impact even when no Markdown file changed. A renamed environment variable, changed default or new error condition may require an update to an existing guide. Conversely, a local refactor may need no new guide if its public behavior remains intact.

Verify commands and examples in the appropriate environment. A syntactically valid command can still use an obsolete flag or omit a prerequisite. Generated API reference can keep signatures current while leaving behavioral descriptions stale. Record what was exercised and what remains a proposed example.

## Review from the next reader’s position

Before merging, set aside the chat and use the repository to answer three questions: what does this component promise, why does its non-obvious behavior exist, and how do I verify a safe change? Missing answers identify documentation work more reliably than a target number of comments.

Use tests to protect important behavior, while preserving the reasoning that tests cannot express clearly. Our [guide to reviewing AI-generated regression tests](https://skillsforbusiness.ai/blog/ai-generated-tests-intended-regression/) explains how to check whether a proposed test detects the intended mistake. Documentation and tests should support the same contract without mechanically repeating each other.

Start with the code being changed. Improve its names, clarify one consequential boundary, retain a verified reason and update the affected instructions. The result should leave the next developer with enough durable context to continue the work, without needing to reconstruct an AI conversation.

## Sources & further reading

Sources checked for this article. Research findings and vendor claims are distinguished in the text.

1.  [What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html)Google Engineering Practices · Accessed 31 October 2026
2.  [Writing Comments — CS 190, Winter 2018](https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/lecture.php?topic=comments)John Ousterhout; Stanford University · Accessed 31 October 2026
3.  [On the Quality of AI-Generated Source Code Comments: A Comprehensive Evaluation](https://arxiv.org/html/2408.14007v3)Guelman et al.; arXiv / AI-SQE 2026 · Accessed 31 October 2026
4.  [Start here — Diátaxis in five minutes](https://www.diataxis.fr/start-here/)Diátaxis · Accessed 31 October 2026

Produced with AI-assisted research and writing. Examples and recommendations are our editorial synthesis unless attributed. This article does not claim independent product testing or human expert review. [Read our editorial policy.](https://skillsforbusiness.ai/blog/editorial/)

## Keep reading

[AI agent timeouts: design retries that do not duplicate work](https://skillsforbusiness.ai/blog/ai-agent-timeouts-safe-retries/)[Check completeness before an AI agent reports all tool results](https://skillsforbusiness.ai/blog/agent-tool-results-pagination-completeness/)
