Skip to content

Commit 0e329fb

Browse files
mihowclaude
andauthored
Document PR title and description conventions (#1332)
* Document PR title and description conventions Adds a Pull Request Conventions section to the project guide: titles lead with the user-facing effect (not the implementation mechanism), and every PR body must open with a plain-language Summary and a user-effect-first List of Changes. Includes the empirical PR-rename analysis that motivated the conventions under docs/claude/analysis/. Co-Authored-By: Claude <noreply@anthropic.com> * Fold title examples into the guide, drop the analysis dataset Move the clearest mechanism-to-effect title examples directly into the Pull Request Conventions section so the guidance is self-contained, and remove the docs/claude/analysis/pr-title-renames.{md,tsv} sweep that was only there as background. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8500e45 commit 0e329fb

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

.agents/AGENTS.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,44 @@ Every call to the AI model API incurs a cost and requires electricity. Be smart
2323
- Do NOT include "Generated with Claude Code" in commit messages
2424
- ALWAYS include "Co-Authored-By: Claude <noreply@anthropic.com>" at the end of commit messages
2525

26+
## Pull Request Conventions
27+
28+
These conventions keep PR titles and descriptions readable for the whole team — product, QA, ops, and engineers who have not seen the diff. The PR template lives at `.github/pull_request_template.md`; the rules below are the parts treated as mandatory.
29+
30+
### Title: lead with the user-facing effect
31+
32+
A title states what the change does for a user, operator, or system, in plain language. It should make sense to someone who has not opened the diff.
33+
34+
- **Effect first, mechanism second.** Push the "how" (serializers, querysets, cache internals, env var names) into the body.
35+
- Avoid: `emit storage URL direct from serializer when cache is warm`
36+
- Prefer: `Store and serve full URLs instead of hitting the web server`
37+
- **Bare sentence-case imperative.** Concrete verb first (Add, Allow, Speed up, Filter, Require, Improve, Stop, Show). No Conventional-Commit prefix (`feat:` / `fix:` / `chore:`) in the title, no code or module names, and no ticket number (reference it in the body with `Closes #N`).
38+
- **Capture the whole PR's purpose, not just the most visible change.** When a PR establishes a pattern, framework, or cleanup that later work builds on, name that intent rather than titling the PR after the one example that demonstrates it. A second clause is fine: "Add cancel button to jobs & establish the pattern for future buttons".
39+
40+
### Body: a Summary and a List of Changes are mandatory
41+
42+
Every PR body opens with:
43+
44+
1. **`## Summary`** — a short, plain-language paragraph stating the purpose of the change and its effect for the user, operator, or system. Written so the whole team can read it; implementation detail belongs in `## Detailed Description` below.
45+
2. **`### List of Changes`** — a numbered list or a table. Each change has, at minimum, a plain user-effect description. Optionally add a column for the technical/implementation detail, plus any other helpful columns (affected area, risk, migration). Lead with the user-effect; do not reduce it to a bare list of class or method names.
46+
47+
### Examples
48+
49+
Real titles from this repository, drafted mechanism-first and then rewritten to lead with the effect:
50+
51+
| Drafted (mechanism) | Rewritten (effect) |
52+
|----|----|
53+
| `perf(api): rewrite collection counts as subqueries; trim capture list SELECT` | Speed up the captures list view |
54+
| `perf(thumbnails): emit storage URL direct from serializer when cache is warm` | Option for thumbnails: store and serve full URLs instead of hitting the server |
55+
| `feat(projects): wire session_time_gap_seconds into event grouping` | Allow users to customize the time gap between sessions |
56+
| `fix(jobs): ack NATS after results-stage SREM; defer task_failure for in-flight async jobs` | Prevent jobs from hanging in STARTED state with no progress |
57+
| `fix(newrelic): make app_name env-var-driven (drop from ini)` | Allow distinguishing data from different deployments in New Relic |
58+
59+
A few patterns worth copying:
60+
61+
- **Name the framework, not the demo.** `feat(post-processing): admin scaffolding precursor (pydantic schema, form base, parameterized template)` became *Framework for admins to trigger and review post-processing methods* — the title captures the capability, not the one example that exercises it.
62+
- **Don't ship the branch-name auto-title.** `gh pr create` pre-fills the title from the branch slug, so titles like `Feat/taxa-covers` or `Fix/celery workers` slip through. Rewrite them: the latter became *Fix background tasks from disappearing*.
63+
2664
## Project Overview
2765

2866
Antenna is an Automated Monitoring of Insects ML Platform. It's a collaborative platform for processing and reviewing images from automated insect monitoring stations, maintaining metadata, and orchestrating multiple machine learning pipelines for analysis.

0 commit comments

Comments
 (0)