# Release-notes news fragments

Each PR with user-visible behavior change drops one tiny markdown file in
this directory. At release prep time the maintainer runs
`pdm run towncrier build --version <X.Y.Z> --yes`, which renders the
fragments into `docs/release_notes/<X.Y.Z>.md` and removes them. The
release workflow surfaces that file in the published GitHub release body.

This per-PR fragment model replaces the old approach where every
contributor edited a shared `docs/release_notes/<version>.md` — that
broke down at LDR's PR throughput (12+ PRs/day, 25–50 PRs per release).

## Naming

```
changelog.d/<id>.<category>.md
changelog.d/+<slug>.<category>.md     # orphan (no PR/issue number)
```

- `<id>` — the PR or issue number (e.g., `3768`). The rendered changelog
  links to it via the `issue_format` template in `pyproject.toml`.
- `+<slug>` — for fragments where no PR/issue number applies. The `+`
  prefix tells towncrier this is an orphan fragment.
- `<category>` — one of the `[[tool.towncrier.type]]` directories
  declared in `pyproject.toml` (currently: `breaking`, `security`,
  `feature`, `bugfix`, `removal`, `misc`).

## What goes in the file

A short user-facing description of the change. One sentence is usually
enough; longer prose is fine for breaking changes that need a "what to
do" line. Markdown is supported.

Examples:

```markdown
# changelog.d/3768.feature.md
Release notes are now prepended to the GitHub release body, with an
AI-generated TL;DR at the top.
```

```markdown
# changelog.d/3670.breaking.md
**`llm.model` no longer auto-fills `gemma3:12b`.** Set the model
explicitly in Settings → LLM, or research will fail loudly with a
clear `ValueError`.
```

## What does NOT go here

- Dependency bumps (the auto-generated PR list catches these).
- CI/workflow tweaks invisible to users.
- Internal refactors with no behavior change.
- Doc-only changes unless the new doc is itself the user-facing point.

If in doubt, ask: *would a user want to read about this on the GitHub
release page?* If no, skip the fragment.

## Categories

| directory   | rendered as          | use for |
|-------------|----------------------|---------|
| `breaking`  | 💥 Breaking Changes  | API/CLI/config that is no longer compatible with prior releases |
| `security`  | 🔒 Security          | CVE fixes, hardening users should know about |
| `feature`   | ✨ New Features      | New user-facing capability |
| `bugfix`    | 🐛 Bug Fixes         | User-visible bug fix |
| `removal`   | 🗑️ Removed           | Removed setting, endpoint, or feature |
| `misc`      | 📝 Other Changes     | Anything else worth highlighting |

## Release flow (for maintainers)

```bash
# As part of release prep:
pdm run towncrier build --version 1.6.9 --yes
# bump __version__.py to 1.6.9
git add src/local_deep_research/__version__.py docs/release_notes/1.6.9.md
git commit -m "chore(release): bump to 1.6.9 + render news fragments"
git push
```

Towncrier (configured under `[tool.towncrier]` in `pyproject.toml` with
`single_file = false` and `filename = "docs/release_notes/{version}.md"`):

1. Reads fragments from `changelog.d/`.
2. Renders them into `docs/release_notes/1.6.9.md`.
3. `git rm`s the consumed fragments (deletion staged for commit).
4. Stages the new release-notes file via `git add`.

To preview without touching anything (e.g., while iterating on a
fragment locally):

```bash
pdm run towncrier build --draft --version 1.6.9
```

The release workflow reads `docs/release_notes/<version>.md` for the
human-narrative input to the published release body.
