Skip to content

Action the review of the agent instruction files - #7347

Open
trexfeathers wants to merge 6 commits into
SciTools:brownfieldfrom
trexfeathers:brownfield-review-actions
Open

trexfeathers wants to merge 6 commits into
SciTools:brownfieldfrom
trexfeathers:brownfield-review-actions

Conversation

@trexfeathers

@trexfeathers trexfeathers commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

(posted by Claude Opus)

Description

Adds a maintainer-notes Sphinx directive, and actions pp-mo's review of the agent instruction files added in #7309. The directive gives module docstrings somewhere to put prose written for a maintainer, so it stays in the file and never reaches the published API page — which is what made "put the explanation in the module docstring" a hard sell. No shipped behaviour changes, so the risk is that a rule now says the wrong thing to future agents, or that the directive hides less than it claims.

The directive is built on docutils and sphinx alone, so it adds no dependency. Its content is never parsed, which means broken markup and unbalanced >>> prompts inside it cannot break a docs build, and the doctest builder ignores them. Getting the name wrong is a build failure rather than a silent leak: make html runs with -W, so an unknown directive stops the build and the content does not render on the way out. A plain reST comment fails the other way round — dedent a single line and the prose is published with a clean build.

Important

One review comment is actioned by deleting a rule rather than qualifying it, which needs a ruling. lib/iris/AGENTS.md banned try/conditional imports in a package __init__.py. That ban sat under Greppability, where it does not belong, since a try-wrapped import of a verbatim name greps perfectly well. It also contradicted the tree in four places: fileformats/__init__.py, io/__init__.py and netcdf/_attribute_handlers.py all defer an iris_grib import, and fileformats/zarr/__init__.py does the same for zarr. I removed the clause and folded the optional-dependency case into the surrounding rule, rather than adding a zarr-shaped exception to a rule four things already break.

Where I would look first, in order of how little I trust myself:

  • The single-exit rule in Size and Shape. pp-mo's exit-flag example is described in prose rather than reproduced as code, so check the description is the shape that was meant.
  • Sixteen module docstrings gain a one-line .. todo:: marking prose to move. Check the selection: the rule I applied was "carries design rationale, traps, invariants or coupling", which excluded netcdf/saver.py and netcdf/ugrid_load.py as short and user-facing.
  • The doctest exemption in tests/AGENTS.md, drawn at changes confined to lib/iris/tests/ or changelog/.

Unrelated and not fixed here: ruff fails on .hooks/check_docs_page_metadata.py with ISC004 on brownfield as it stands, which pre-commit run --all-files surfaces.

Verified by building the docs, not by reading the Sphinx manual

A full html-noplot build with the API pages produced 332 pages. The .. todo:: markers appear in none of them, and the surrounding docstring prose still renders.

Injecting a maintainer-notes block containing deliberately broken markup and an unbalanced doctest prompt into cf/__init__.py built cleanly and published nothing; that injection was then reverted. Misspelling the directive gives ERROR: Unknown directive type and exit 1 under -W, with the content absent from the output. todo_include_todos and todo_emit_warnings are both already False in conf.py, so the markers render nothing and add no build noise.

All seven review comments, and what each did to the files
Comment Outcome
Doctests run before finishing Actioned. The "only if you touched a >>> example" carve-out is gone, and the requirement is on the Pre-Finish Checklist as asked.
import * as its own rule Actioned. Split out of the __all__ bullet, with no explanation attached.
iris.fileformats.zarr breaks the __init__.py rules Actioned by deleting the clause, as above.
Multi-level graphs Actioned. Measured first: on Dask 2026.8.0, da.zeros((10000, 10000), chunks=(100, 100)) holds 10000 keys and [:100, :100] of it holds 10001, culled to 2 only at optimize time. The numbers stayed out of the file.
Maintainer information in a comment Answered in the thread at the time. The directive is the eventual answer: maintainer prose now has a home that is not published.
State the purposes of docstrings and comments Actioned. A paragraph naming the three channels and their readers now opens the section.
Guard clauses and early returns Actioned. Of the functions in lib/iris that contain a return, 95% have exactly one, so the old bullet argued against the surrounding code.
Rejected: a zarr exception bullet, a compliance hook, and converting the docstrings here

A separate bullet exempting iris.fileformats.zarr was written and then removed. It gave one module the weight of a rule, and zarr is not the exception.

Converting the sixteen marked docstrings is deliberately left out. The prose has to be read and sorted, and several of the files are under active development, so a wide diff would conflict with work in flight for no gain.

A hook flagging # NOTE: runs longer than three lines was considered, as the only mechanical signal that an agent skipped the block. It would fire on 34 existing sites, all human-authored and pre-dating the convention, so it was dropped.

lib/iris/AGENTS.md ends at 300 lines, meeting the cap its own meta-instruction sets, which it did not before — the branch started at 303. The room came from tightening Module Docstrings Carry the Explanation, where three sentences were said twice: that inline comments scatter an argument and that a side Markdown file rots unseen are both Fast Rule 7, and that misspelling the directive fails the build is in the directive's own module docstring. Two structural savings were considered and dropped: the meta-instruction block is byte-identical in four AGENTS.md files and could become a pointer, but it is too important to demote; the Where Human and Agent Preferences Diverge table mostly restates rules stated elsewhere, but folding it is a change nobody asked for.

pp-mo's review of the .hooks additions on brownfield is still to come, and will be actioned on this branch too.

Checklist

Not applicable to this branch: a What's New entry, type hints, benchmarks and dependencies. Nothing here changes shipped behaviour, and the directive adds no package requirement.

  • Checked if tests need updating
  • Checked if documentation needs updating
  • Confirmed that the GitHub 'checks' on this PR are passing ✅

trexfeathers and others added 2 commits October 26, 2026 13:10
Separate "never import *" from the __all__ rule, and drop the ban on
conditional imports in a package __init__.py. The ban sat under
Greppability, where it does not belong: a try-wrapped import of a verbatim
name greps perfectly well. It also contradicted the tree, where iris_grib
and iris.fileformats.zarr both defer an optional dependency's import.

Record that indexing does not shrink a Dask graph. A slice still references
every chunk of its source, and is culled only at compute.

State the purposes of a docstring, a comment and a module docstring at the
head of the section that governs all three.

Replace the guard-clause advice with a single-exit rule. Nearly every
function in lib/iris that contains a return has exactly one, so the old
wording argued against the surrounding code.

Delete the prose describing the sphinx-needs item a public module docstring
carries. The check_docs_page_metadata hook enforces it, and names the
expected type, the line limit and the missing tag when it fails.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A doctest asserts real output, so a change anywhere in the library or the
user guide can break one. Nothing in the pytest suite covers them, so the
previous rule - run them only if you edited a >>> example - left those
breakages to CI. Exempt only changes confined to lib/iris/tests/ or to
changelog/, which cannot reach a doctest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.88%. Comparing base (426d718) to head (95d5d85).

Additional details and impacted files
@@             Coverage Diff             @@
##           brownfield    #7347   +/-   ##
===========================================
  Coverage       90.88%   90.88%           
===========================================
  Files             104      104           
  Lines           26813    26813           
  Branches         4898     4898           
===========================================
  Hits            24369    24369           
  Misses           1689     1689           
  Partials          755      755           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

trexfeathers and others added 4 commits October 26, 2026 14:24
A module docstring is the only prose read on every visit to a module and
reviewed in the diff, which makes it the right home for subsystem
explanation. Sphinx publishes it, so prose written for a maintainer arrives
in front of a user. This directive drops its content instead, leaving it in
the file and off the page.

Built on docutils and sphinx alone, so it adds no dependency. The content is
never parsed, which makes broken markup and unbalanced doctest prompts safe
to write and keeps the doctest builder away from them. Misspelling the name
stops the build, because make html runs with -W, and the content does not
render on the way out. A plain reST comment fails the other way: dedent one
line and the prose is silently published.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Names the block in the three places lib/iris/AGENTS.md already sends
maintainer-facing prose: the summary of which channel serves which reader,
the brevity rule that sorts a sentence by who it is for, and the home for a
surprise no test can pin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sixteen module docstrings carry maintainer-facing prose - design rationale,
traps, invariants, coupling - and each gains a one-line todo at the point the
maintainer-notes block will go.

Converting them is a separate change. The prose has to be read and sorted,
and several of these files are under active development, so a wide diff here
would conflict with work in flight for no gain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three of the removed sentences were said twice. That inline comments scatter
an argument, and that a companion Markdown file rots unseen, are both Fast
Rule 7. That misspelling the directive fails the build is in the directive's
own module docstring.

lib/iris/AGENTS.md now fits the 300-line cap its meta-instruction sets,
which it did not before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant