Skip to content

Commit 83877be

Browse files
authored
docs(agents): write down the versioning policy (#352)
1 parent bdf98ad commit 83877be

1 file changed

Lines changed: 17 additions & 4 deletions

File tree

‎AGENTS.md‎

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,22 @@ Before pushing a raised dependency floor, run the `floors` steps from
2828
[`_checks.yml`](.github/workflows/_checks.yml) locally. If resolution fails, raise the direct floor
2929
it names.
3030

31+
## Versioning
32+
33+
- **A change is breaking when a user's working code or deployed behaviour changes without them
34+
editing anything:** a new default, a removed or renamed public name or config field, a changed
35+
HTTP surface (path, status code, response body), or a raised dependency floor that the previous
36+
floor ran correctly with. Correcting a floor the code never worked with is a fix.
37+
- **A breaking change ships only in a major release.** One exception: dropping a Python version past
38+
its end of life ships in a minor, as 1.11.0 did for 3.10. Installers skip a release whose
39+
`requires-python` excludes the running interpreter, so no deployed service breaks.
40+
- **A rename keeps the old name working, with a `DeprecationWarning`, for at least one minor, and
41+
the next major deletes it.** The warning names that major. A module-level name goes through
42+
`deprecated_module_getattr` plus a `typing.TYPE_CHECKING` alias so type checkers still see it; a
43+
config field goes through `BaseConfig._renamed_fields`.
44+
- **Every breaking change gets a line in a "Breaking changes" section of the release notes**, as
45+
[1.12.0](https://github.com/modern-python/lite-bootstrap/releases/tag/1.12.0) has.
46+
3147
## Agent skills
3248

3349
### Issue tracker
@@ -44,13 +60,10 @@ Single-context: `CONTEXT.md` and `docs/adr/` at the repo root. See `docs/agents/
4460

4561
## Code style
4662

47-
Four rules that are not visible in the code that follows them:
63+
Three rules that are not visible in the code that follows them:
4864

4965
- **No `# noqa: PLR2004`.** Extract the magic value to a named local instead:
5066
`expected_max_age = 600; assert config.cors_max_age == expected_max_age`.
51-
- **A public rename ships a silent alias.** `OldName = NewName` at the end of the module, re-exported
52-
from `__init__.py` if the old name was. A class assignment, not a subclass, so `isinstance` still
53-
holds; `OpentelemetryConfig` is the worked example.
5467
- **A warning reached from config construction or an instrument's `bootstrap()` goes through
5568
`warn_at_caller`.** Neither depth is constant: a `__post_init__` cascade runs as deep as that
5669
config's MRO, and `bootstrap()` sits a frame deeper whenever it calls `super().bootstrap()`. So

0 commit comments

Comments
 (0)