Keep Developer Documentation Aligned with an Agent's Code Change
Drafted and reviewed using AI assistance.
On this page
After an agent changes a configuration name, update the instructions a developer will follow: the example command, accepted values, default behavior, error handling, and migration note. Trace each statement to the changed source. Keep a command's execution status separate from what the code appears to do.
A polished summary such as “improved reporting configuration” does not tell the next developer which variable to set. A README that retains the old variable can be more misleading than a missing explanation: the command may still run while silently using a default.
This guide builds a small, fictional reporting script and its revised README. The code, paths, and previous documentation below are original teaching materials. Commands and outputs are illustrative; they have not been executed for this article.
Start with the action the reader needs to take
Imagine a developer who wants JSON output from a local reporting script. The agent has renamed an environment variable and added validation. The documentation task is to let that developer choose the format and recognize an invalid setting.
The fictional previous implementation selected the format using:
output = os.environ.get("REPORT_FORMAT", "text")
Its previous README said:
## Print a report
Run the script from the repository root:
```sh
REPORT_FORMAT=json python3 tools/summary.py
```
Set REPORT_FORMAT to json for structured output. Omit it for text.
That text describes the old setting. It says nothing about invalid values because the example's new validation did not exist at that stage.
Before rewriting, identify all the reader actions affected by the change. Here there are three: run the default report, request JSON, and fix a rejected value. The migration from an old command is a fourth action worth making explicit.
Read the changed code before writing the explanation
Here is the complete replacement script for this fictional example, at tools/summary.py:
import json
import os
import sys
def main():
output = os.environ.get("REPORT_OUTPUT", "text")
if output not in {"text", "json"}:
print("REPORT_OUTPUT must be text or json", file=sys.stderr)
return 2
summary = {"open": 3, "total": 8}
if output == "json":
print(json.dumps(summary, sort_keys=True))
else:
print(f"Open: {summary['open']}; total: {summary['total']}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
The small source makes several documentation decisions possible. Only REPORT_OUTPUT is read. Missing configuration selects text. The two accepted strings are lowercase and matched exactly. An empty string is therefore invalid. Invalid configuration returns before a report is printed.
The source does not implement a compatibility alias for REPORT_FORMAT. Keeping the old README command would not request JSON from this replacement script. If REPORT_OUTPUT is absent, the script takes the text branch even when the old variable is present.
These observations come from the displayed source, rather than an agent's account of what it intended to change. They are also narrower than a runtime claim. Reading this code does not establish that a repository contains the file at the documented path or that a reader has a working interpreter.
Map code facts to documentation locations
Use a short mapping to catch incomplete edits. Fill it with the actual identifiers and branches from the change.
| Fact in the example source | Documentation location | Required edit |
|---|---|---|
os.environ.get("REPORT_OUTPUT", "text") |
Configuration and quick examples | Replace the old variable; describe the default |
Accepted set is {"text", "json"} |
Configuration table | List both exact lowercase values |
Invalid values return 2 before formatting |
Error handling | Describe the error and absence of report output |
Error is printed to sys.stderr |
Error handling | Distinguish diagnostic output from report output |
No reference to REPORT_FORMAT remains in the displayed script |
Migration note | Explain that the old setting is no longer read |
JSON branch uses the summary object |
JSON example | Show only the two fields this example contains |
Main block exits with main()'s return value |
Exit behavior | Describe intended success and failure exit codes |
This is a maintenance aid, not a second specification to keep forever. Once the documentation is revised, the source and the reader-facing instructions remain the important artifacts. A review note can retain the mapping when it helps explain a non-obvious migration.
Replace the whole affected README section
Editing only the variable in the first command leaves room for contradictory prose below it. Here is a complete replacement section that covers the reader's actions without adding features absent from the code:
## Print a sample report
This script prints a fixed teaching sample with 3 open items out of 8 total
items. It does not read a database or calculate live project totals.
### Requirements and location
Save the accompanying example as tools/summary.py. The commands below use
a POSIX-style shell and an available Python 3 interpreter named python3.
Run them from the directory containing tools/.
These commands and outputs are illustrative examples, not recorded runs.
Check the interpreter and command behavior in your target environment.
### Choose an output format
| Variable | Accepted values | When absent |
| --- | --- | --- |
| REPORT_OUTPUT | text, json | text |
Values are case-sensitive. An empty value is invalid.
For text, set the format explicitly:
```sh
REPORT_OUTPUT=text python3 tools/summary.py
```
Expected text for the accompanying sample:
```text
Open: 3; total: 8
```
For JSON:
```sh
REPORT_OUTPUT=json python3 tools/summary.py
```
Expected JSON for the accompanying sample:
```json
{"open": 3, "total": 8}
```
When REPORT_OUTPUT is absent, the script selects text. If your shell
already defines it, invoking the script without a prefix uses that value.
### Invalid configuration
A value other than text or json is intended to produce this diagnostic on
standard error and exit with status 2, without printing a report:
```text
REPORT_OUTPUT must be text or json
```
The success branches return status 0.
### Migrate the old setting
Replace REPORT_FORMAT with REPORT_OUTPUT in scripts and local command
examples. This version does not read REPORT_FORMAT. Setting only the old
variable leaves REPORT_OUTPUT absent and therefore selects text, unless
REPORT_OUTPUT is already set elsewhere in the environment.
Notice the small environment qualification. “Omit the variable for text” is incomplete if a developer has already exported a different value. Documentation should describe the condition the code checks: absence from the process environment.
Separate source review from execution
For this article, the completed work is the source example, mapping, and replacement documentation. The following execution checks remain to be performed if the example is adopted:
| Check | Expected behavior from the displayed source | Execution status here |
|---|---|---|
REPORT_OUTPUT absent |
Text branch; status 0 | Not run |
REPORT_OUTPUT=json |
JSON branch; status 0 | Not run |
REPORT_OUTPUT=JSON |
Diagnostic on standard error; status 2 | Not run |
REPORT_OUTPUT set to an empty string |
Same invalid-value behavior | Not run |
Only REPORT_FORMAT=json set |
Old variable ignored; text when new variable is absent | Not run |
When applying the method to a real repository, record the exact revision, environment, command, and observed result for any check you actually execute. If a command cannot run, preserve that limitation instead of copying another environment's success into the README.
GitHub's repository instruction guidance calls for build and validation instructions grounded in the repository, including command prerequisites and verification. The worked example here is an editorial application of that principle, rather than a GitHub-prescribed README format.
Give the next agent a bounded documentation request
Use a request that names the reader action and the evidence to follow:
Update the reporting instructions to match this code change.
Read the current tools/summary.py and the affected README section first.
Map configuration names, accepted values, defaults, errors, and migration
behavior to the source before editing. Use the current implementation
as evidence; do not expand the previous agent's summary into new features.
Replace contradictory examples and prose together. Keep the explanation
focused on choosing a format and recovering from invalid configuration.
Report which commands you actually ran, with the environment and result.
Mark unexecuted checks as pending. Return the documentation diff and any
code/documentation conflict that needs a separate implementation decision.
If the code and intended behavior disagree, identify that conflict before making the README sound certain. The next developer needs instructions that match the available implementation, plus a clear account of what still requires a decision or a run.