Port the added-fact documentation rule from
XomniaAI/agentic-engineering-loop#434
into the template's AGENTS.md, so generated projects tell their agents to keep
docs, docstrings, and comments short.
Why
The template already enforces docstring presence — ruff D with the numpy
convention in template/pyproject.toml.jinja — but nothing bounds their
length. Agents working in a freshly generated project therefore produce
Parameters/Returns blocks that restate the annotations, step-by-step
narrations of the implementation, and docstrings that only grow on every edit.
Upstream #434 fixed exactly this gap in the loop's own AGENTS.md with a single
rule: past the summary line, a line must carry a fact the code cannot.
template/AGENTS.md is the natural home — it is the file template/CLAUDE.md
includes (@AGENTS.md), and it currently holds only Package Management and
Git Conventions.
Scope
Two files, both under template/:
-
template/AGENTS.md — append the new section (see verbatim text below).
-
tests/test_template.py — in test_template_renders, add coverage that the
agent-instruction files actually land in a generated project:
assert (project_path / "AGENTS.md").is_file()
assert (project_path / "CLAUDE.md").is_file()
No other file changes.
Exact text to add
Append at the end of template/AGENTS.md, after the Git Conventions
section, separated by one blank line. Heading is Title Case to match the two
existing headings (upstream uses sentence case; the template does not). Prose
wrapped at 80 columns. template/AGENTS.md is a static file (no .jinja
suffix), so it must contain no Jinja expressions — do not reference
{{ project_slug }} or any other variable.
## Documentation and Comment Style
Brevity is not tidiness — it is what gets the text read. A docstring, comment,
or page nobody reads still has to be maintained, so it is worse than none.
Docstring *presence* is enforced by ruff's `D` rules (numpy convention) in
`pyproject.toml`. This section bounds their *length*.
The unit of judgement is the *added fact*: after the summary line, every line
must tell the reader something they cannot get from the name, the signature,
the type hints, or the code itself.
Earns more than a summary line:
- a contract the signature doesn't show — preconditions, invariants, what it
raises
- units, bounds, or formats a type can't carry (`timeout: float` — seconds or
milliseconds?)
- caller-visible behaviour that would surprise — mutation, ordering,
idempotency, blocking, retries, cost (a network round-trip, an LLM call)
- a pointer to the *why* when it isn't obvious (link the issue or ADR, don't
restate it)
Does not:
- restating the signature, or a numpy `Parameters`/`Returns` section where the
name and type already say it
- narrating the implementation step by step — that's the code
- history ("previously…", "refactored to…") — that's git
- examples for a function whose use is obvious from its name
The same rule governs prose: the README covers what a reader needs to install,
run, and maintain the project; implementation detail belongs in the code.
Prefer a list, table, or short code example over paragraphs. When editing an
existing docstring, comment, or page, it must not get longer unless behaviour
was added.
Deliberately not ported from #434
- The
docs/source/contributing/code_style.md half. The template ships no
Sphinx docs/ tree and no contributing guide, so that counterpart has no
target here. AGENTS.md is the single source.
- Loop-specific wording. "the cost of spawning a Claude run" becomes the
generic "a network round-trip, an LLM call"; "docs/ covers behaviour needed
to operate or maintain the loop" becomes the README sentence above.
- The port-inheritance rewording — specific to the upstream codebase (also
dropped by #434 itself relative to its own upstream).
Out of scope
- Adding a root-level
AGENTS.md for the copier_python repo itself.
- Adding a
docs/ tree or CONTRIBUTING.md to the template (that belongs in
its own issue if wanted).
- Changing the ruff
D selection or its ignore list in
template/pyproject.toml.jinja.
- Retro-fitting the rule onto the template's existing docstrings in
template/src/{{ project_slug }}/*.jinja — they are already one-liners and
comply.
Acceptance criteria
Verification
cd /workspace/copier_python
uv run pytest tests -q
The suite generates a project into a temp dir, runs uv sync, then make lint,
make test, and pre-commit run --all-files inside it — so it needs network
access and takes a few minutes. Nothing in the added text is executable, so a
green suite plus a read of the rendered AGENTS.md is the full check.
Risk
Low. Documentation-only text in a static template file, plus two assertions.
Worst case is wording taste, reviewable in the diff.
Port the added-fact documentation rule from
XomniaAI/agentic-engineering-loop#434
into the template's
AGENTS.md, so generated projects tell their agents to keepdocs, docstrings, and comments short.
Why
The template already enforces docstring presence — ruff
Dwith the numpyconvention in
template/pyproject.toml.jinja— but nothing bounds theirlength. Agents working in a freshly generated project therefore produce
Parameters/Returnsblocks that restate the annotations, step-by-stepnarrations of the implementation, and docstrings that only grow on every edit.
Upstream #434 fixed exactly this gap in the loop's own
AGENTS.mdwith a singlerule: past the summary line, a line must carry a fact the code cannot.
template/AGENTS.mdis the natural home — it is the filetemplate/CLAUDE.mdincludes (
@AGENTS.md), and it currently holds only Package Management andGit Conventions.
Scope
Two files, both under
template/:template/AGENTS.md— append the new section (see verbatim text below).tests/test_template.py— intest_template_renders, add coverage that theagent-instruction files actually land in a generated project:
No other file changes.
Exact text to add
Append at the end of
template/AGENTS.md, after the Git Conventionssection, separated by one blank line. Heading is Title Case to match the two
existing headings (upstream uses sentence case; the template does not). Prose
wrapped at 80 columns.
template/AGENTS.mdis a static file (no.jinjasuffix), so it must contain no Jinja expressions — do not reference
{{ project_slug }}or any other variable.Deliberately not ported from #434
docs/source/contributing/code_style.mdhalf. The template ships noSphinx
docs/tree and no contributing guide, so that counterpart has notarget here.
AGENTS.mdis the single source.generic "a network round-trip, an LLM call"; "
docs/covers behaviour neededto operate or maintain the loop" becomes the README sentence above.
dropped by #434 itself relative to its own upstream).
Out of scope
AGENTS.mdfor thecopier_pythonrepo itself.docs/tree orCONTRIBUTING.mdto the template (that belongs inits own issue if wanted).
Dselection or its ignore list intemplate/pyproject.toml.jinja.template/src/{{ project_slug }}/*.jinja— they are already one-liners andcomply.
Acceptance criteria
template/AGENTS.mdends with the Documentation and Comment Stylesection, matching the text above; the existing Package Management and
Git Conventions sections are unchanged.
{{,{%) introduced intemplate/AGENTS.md.tests/test_template.py::test_template_rendersasserts bothAGENTS.mdand
CLAUDE.mdexist in the generated project.uv run pytest testspasses (all tests, including the renderedproject's
make lint,make test, and pre-commit run).docs:prefix and carries noCo-Authored-Byorother AI attribution trailer, per the template's own Git Conventions.
Verification
cd /workspace/copier_python uv run pytest tests -qThe suite generates a project into a temp dir, runs
uv sync, thenmake lint,make test, andpre-commit run --all-filesinside it — so it needs networkaccess and takes a few minutes. Nothing in the added text is executable, so a
green suite plus a read of the rendered
AGENTS.mdis the full check.Risk
Low. Documentation-only text in a static template file, plus two assertions.
Worst case is wording taste, reviewable in the diff.