Skip to content

Commit 89b88f0

Browse files
committed
Docs(refactor[agents]): Route instead of restate
why: AGENTS.md is read on every task, so a policy that matters to one class of change costs context on all the others. Splitting how we work from how we write lets each be loaded when it applies, and keeps both discoverable to humans rather than only to agents. what: - Replace AGENTS.md body with a router: the project map, universal change discipline, then one pointer per class of change - Add .github/WRITING.md, the fullest "Documented examples that run" section in the fleet: both collection paths (.py delegates to pytest's own DoctestModule; .rst/.md go through DocutilsDocTestFinder), every directive form (doctest_block, .. doctest::/{doctest}, testsetup/testcleanup), and what each registered flag (ALLOW_UNICODE, ALLOW_BYTES, NUMBER, HIDE) actually does versus the stdlib set - Document, verified against source and tests, that testsetup/ testcleanup do not share globals across blocks the way Sphinx's own testsetup does, and that docs/justfile's doctest recipe is not run by CI - Add .github/CONTRIBUTING.md with this repo's real gates, matrix, and release process, read from pyproject.toml, the justfile, and the workflows - Fix README: unverified PyPy support claim, docutils/myst-parser minimum-requirements section against actual pyproject.toml pins, a typo naming the package, and a "We"-voiced sentence; preserve every link and all three `>>> ` prompts - Replace docs/project/contributing.md and code-style.md with pointer pages to the canonical files; an {include} was tried and produces dead cross-file anchors on this repo's Sphinx, confirmed by inspecting the built HTML - Delete docs/AGENTS.md and docs/CLAUDE.md (absorbed into WRITING.md) and the lowercase .github/contributing.md (replaced)
1 parent 5dac742 commit 89b88f0

9 files changed

Lines changed: 1156 additions & 1053 deletions

File tree

‎.github/CONTRIBUTING.md‎

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# Contributing
2+
3+
Thanks for looking. gp-libs is pre-1.0 (`0.0.x`); a minor version bump may
4+
still carry a breaking change. Bug reports with a reproduction, and notes on
5+
where the documentation misled you, are the most useful contributions right
6+
now.
7+
8+
How this project writes prose — README, `CHANGES`, release notes, commit
9+
messages, docstrings, source comments, and log messages — is set out
10+
separately in [WRITING.md](WRITING.md). Read that before changing any of it.
11+
The constraints every change is held to, and the map of what is where, are in
12+
[AGENTS.md](../AGENTS.md).
13+
14+
## Getting set up
15+
16+
Install [git], [uv], and [just].
17+
18+
```console
19+
$ git clone https://github.com/git-pull/gp-libs.git
20+
```
21+
22+
```console
23+
$ cd gp-libs
24+
```
25+
26+
```console
27+
$ uv sync --all-extras --dev
28+
```
29+
30+
[git]: https://git-scm.com/
31+
[uv]: https://github.com/astral-sh/uv
32+
[just]: https://just.systems/
33+
34+
## The gates
35+
36+
Format:
37+
38+
```console
39+
$ uv run ruff format .
40+
```
41+
42+
Lint:
43+
44+
```console
45+
$ uv run ruff check . --fix --show-fixes
46+
```
47+
48+
Type-check — strict mypy across `src/` and `tests/`:
49+
50+
```console
51+
$ uv run mypy .
52+
```
53+
54+
Test:
55+
56+
```console
57+
$ uv run pytest
58+
```
59+
60+
**Imports.** Namespace stdlib imports — `import enum`, not
61+
`from enum import Enum` — so a call site reads `enum.Enum`. Third-party
62+
packages may use `from X import Y`. For typing, `import typing as t` and
63+
access via the namespace: `t.NamedTuple`, `t.TYPE_CHECKING`. Every file
64+
starts with `from __future__ import annotations`; ruff's isort
65+
`required-imports` (`pyproject.toml`) enforces that one, the rest is
66+
convention ruff does not check.
67+
68+
Documentation is a gate, not a courtesy. Examples in `src/*.py` docstrings
69+
and under `docs/` are executed by `uv run pytest`, because `testpaths` in
70+
`pyproject.toml` lists `tests`, `docs`, and `src`; `README.md` is not in
71+
`testpaths`, so its three `>>> ` examples do not currently run under CI.
72+
There is no separate doctest step for the paths that are collected — a
73+
green `pytest` is the proof. Which blocks qualify, and the one mistake that
74+
silently removes a test, are in
75+
[WRITING.md](WRITING.md#documented-examples-that-run).
76+
77+
Before claiming a test or a gate works, show it failing. A gate that has
78+
never been red is an assumption.
79+
80+
CI (`.github/workflows/tests.yml`) runs the equivalent of the four commands
81+
above (`ruff check .`, `ruff format . --check`, `mypy .`,
82+
`py.test --cov=./ --cov-report=xml`) across a matrix of Python 3.10-3.14,
83+
docutils 0.20 and 0.22.4, and pytest 8 and 9 — gp-libs supports a wider
84+
version span than most consumers of it, because everything downstream
85+
depends on this collector staying compatible.
86+
87+
## Tests
88+
89+
Write tests as standalone functions, not classes — no `class TestFoo:`
90+
groupings. Use descriptive function names and file organization instead.
91+
92+
Prefer fixtures from `tests/conftest.py` over `monkeypatch` and
93+
`unittest.mock` when one exists; document in the test docstring why a
94+
standard fixture was not used for an exceptional case. Use `tmp_path`
95+
(`pathlib.Path`) over `tempfile`, and `monkeypatch` over `unittest.mock`
96+
when you do need one.
97+
98+
`tests/conftest.py` also provides the Sphinx `app_params`/`make_app_params`
99+
fixtures (via `pytest_plugins = ["sphinx.testing.fixtures", "pytester"]`)
100+
for tests that build a throwaway Sphinx app — used by
101+
`tests/test_linkify_issues.py` and the plugin-suppression tests.
102+
`tests/regressions/` holds one file per historical bug, named for its
103+
issue.
104+
105+
Run continuously with [pytest-watcher]:
106+
107+
```console
108+
$ just start
109+
```
110+
111+
Or with [entr(1)] when you want a shell-only watcher:
112+
113+
```console
114+
$ just watch-test
115+
```
116+
117+
[pytest-watcher]: https://github.com/olzhasar/pytest-watcher
118+
[entr(1)]: http://eradman.com/entrproject/
119+
120+
## Documentation
121+
122+
Build the docs:
123+
124+
```console
125+
$ just build-docs
126+
```
127+
128+
Start the default preview server, which watches for file changes:
129+
130+
```console
131+
$ just start-docs
132+
```
133+
134+
From inside `docs/`, the local `docs/justfile` has finer-grained recipes:
135+
`just html` builds once, `just serve` serves the built output, `just watch`
136+
rebuilds on change, `just dev` watches and serves together, and
137+
`just design` disables incremental builds while you edit static assets.
138+
139+
`docs/conf.py` also enables `sphinx.ext.doctest` with a
140+
`doctest_global_setup` that imports `is_allowed_version` and
141+
`pytest_ignore_collect`, so the `{doctest}` blocks under `docs/` are valid
142+
input to Sphinx's own doctest builder as well as to pytest. Run it with
143+
`just -f docs/justfile doctest`. Neither `tests.yml` nor `docs.yml` invokes
144+
that recipe — it is a manual, local-only check, not a CI gate. `just
145+
build-docs` is what CI runs, and it is also the only thing that catches a
146+
broken `{ref}`/`{doc}` cross-reference; the doctests do not.
147+
148+
## Releasing
149+
150+
gp-libs is pre-1.0: minor version bumps may include breaking changes. [uv]
151+
handles virtualenv creation, package requirements, versioning, building,
152+
and publishing — there is no `setup.py` or requirements file.
153+
154+
1. Update `CHANGES` with release notes.
155+
2. Bump the version in `src/gp_libs.py` and `pyproject.toml`.
156+
3. Create the release commit:
157+
158+
```console
159+
$ git commit -m 'Tag v0.1.1'
160+
```
161+
162+
4. Push the branch for review:
163+
164+
```console
165+
$ git push
166+
```
167+
168+
5. After review, the release owner creates and pushes the tag. Never
169+
create tags. Never push tags. The owner handles tagging and tag pushes,
170+
because a tag triggers the publish workflow. See
171+
[Release commits](WRITING.md#release-commits).
172+
173+
## Pull requests
174+
175+
One subject per pull request. Unrelated cleanup found along the way
176+
belongs in its own commit, and usually in its own pull request.
177+
178+
Discuss a substantial change via an issue before making it.
179+
180+
Commit format is in [WRITING.md](WRITING.md#commits).
181+
182+
## Decorum
183+
184+
- Participants will be tolerant of opposing views.
185+
- Participants must ensure that their language and actions are free of
186+
personal attacks and disparaging personal remarks.
187+
- When interpreting the words and actions of others, participants should
188+
always assume good intentions.
189+
- Behaviour which can be reasonably considered harassment will not be
190+
tolerated.
191+
192+
Based on [Ruby's Community Conduct Guideline](https://www.ruby-lang.org/en/conduct/).
193+
194+
## Security
195+
196+
Please do not open a public issue for a vulnerability. Report it privately
197+
through GitHub:
198+
<https://github.com/git-pull/gp-libs/security/advisories/new>.

0 commit comments

Comments
 (0)