Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .claude/rules/docstrings.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ traps to keep front-of-mind on touch:
in the decision layer only: `docs/adr/`, `CONTEXT.md`, `.claude/rules/`,
`docs/guides/`.
- Module docstring opens with `"""This is a script for ..."""` (CLAUDE.md §3).
- **A docstring is NOT a changelog — never stack `.. versionchanged::` at class or
method level.** One `.. versionadded::` per public symbol (when the symbol first
appeared) is all that belongs there. A behaviour change goes on the **parameter that
changed**, inside that parameter's description; everything else belongs in
`CHANGELOG.md` and the release notes. A 2026-06-01 pass backfilled version history
into docstrings package-wide (242 `versionadded`, 40 `versionchanged`, 11 in `_cpp.py`
alone) and the result reads as history burying behaviour — `CPP.__init__`'s docstring
tripled from 36 to 117 lines. **When you add a feature, its rationale goes in the
changelog, not in the constructor docstring.** Full rule: *Versioning & deprecation*
in `docs/source/index/docstring_guide.rst`.
- **Example/tutorial notebooks** (the `.ipynb` behind each `examples/<name>.rst`)
show DataFrames with `aa.display_df(df, n_rows=10, show_shape=True)` — never
`print(df)` / bare `df` / `df.head()` (CLAUDE.md §3).
Expand Down
28 changes: 25 additions & 3 deletions docs/source/index/docstring_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,20 @@ Citations
Versioning & deprecation
------------------------

**A docstring is not a changelog.** The release history lives in ``CHANGELOG.md`` and in
the rendered *Release Notes*; a docstring says what the object does **today**.

* ``.. versionadded:: X.Y.Z`` (true first-release version) on every public class
and function; ``.. versionchanged:: X.Y.Z`` when behaviour changes.
* **Parameter-level directives** — when a *parameter or option* is added/changed
after its class, annotate it inside the parameter description:
and function — **exactly one**, marking when the symbol itself first appeared.
* **Never stack** ``.. versionchanged::`` **entries at class or method level.** A
method that accumulates "Changed in version …" blocks buries what it *does*
under what happened to it, and the reader who wants history is better served by
the release notes. If a behaviour change is important enough to surface in the
API docs, it belongs on the **parameter that changed** (below), and otherwise
only in ``CHANGELOG.md`` / the release notes.
* **Parameter-level directives are the rule, not the alternative** — when a
*parameter or option* is added or changed after its class, annotate it inside
that parameter's description and nowhere else:

.. code-block:: text

Expand All @@ -270,6 +280,18 @@ Versioning & deprecation

.. versionadded:: 1.1.0

The same for a changed default or a changed meaning: put the note under that
parameter, not in the method's prose.

.. code-block:: text

n_batches : int, optional
Number of scale-axis batches. Output is byte-identical to the
single-pass result.

.. versionchanged:: 1.2.0
The multiple-testing correction is pooled across batches.

* **Deprecation** uses ``.. deprecated:: X.Y.Z`` in the docstring plus a
``DeprecationWarning`` shim (see :ref:`api-stability <usage_principles>`); a
renamed/removed public symbol keeps a one-minor-release shim before removal.
Expand Down
Loading