ADR 0013: Changelog and Release Notes

Ratification

Adopted before ADR 0018. There was no separate ratification process. Git history for this file on main is the record.

Context

Why this matters: When something breaks in production, the first question is “what changed?” A changelog in the repo answers that without digging through dozens of commits. It is also the polite surface for integrators: they should not have to read your internal tickets to learn about API or security changes.

Ad hoc notes in chat do not scale. We keep Keep a Changelog at the repository root, aligned with Docs as Code, and enforce updates when user-facing paths change.

Decision

Where and how

Merge and PR conventions

Automation (LLM)

An optional script may call an HTTP API (OpenAI-compatible or similar) using keys from the developer or CI environment to draft bullet points from git log. The output is assistive only: humans review and edit before merge. Nothing automatically overwrites CHANGELOG.md on main without a normal PR.

Local workflow: scripts/changelog_draft.py

The script does not write CHANGELOG.md. You copy or adapt its stdout into [Unreleased] in a normal commit/PR.

  1. What --since and --head mean. It uses the same range as Git: since..head means commits reachable from head that are not in since (for example new work on your branch that is not yet in main). Defaults: --since main --head HEAD.
  2. Do you need a new branch? Not for the script itself. For collaboration, use a feature branch and open a PR; point --head at that branch name or stay checked out on it and use --head HEAD.
  3. git add is not enough. Until you git commit, your changes are not in the history, so main..your-branch can show no commits even if files are staged. The script then prints _No changes in this range._ (or hints on stderr).
  4. Draft before a commit. Run python scripts/changelog_draft.py --since main --head HEAD --include-working-tree. That adds git diff --cached --stat (staged) and git diff --stat (unstaged) to the prompt so the model can summarize work that is not committed yet.
  5. After one or more commits on the branch. Omit --include-working-tree (or keep it if you still have local edits). Example: python scripts/changelog_draft.py --since main --head feature/my-feature.
  6. Inspect the prompt without calling the API: python scripts/changelog_draft.py --print-log (add the same flags you would use for a real run).
  7. Save the draft to a file: python scripts/changelog_draft.py ... -o /tmp/changelog-llm-draft.md writes UTF-8 in addition to stdout. Still merge into CHANGELOG.md by hand under the right ### headings — do not raw-append stdout to the changelog file.
  8. Secrets (local only). Set OPENROUTER_API_KEY or OPENAI_API_KEY in the repository root .env file (see env/example). Optional: OPENAI_BASE_URL, OPENAI_MODEL, OpenRouter attribution headers described there.
  9. Smoke-test the API key: make llm-ping or python scripts/llm_ping.py.
  10. One-step draft (Makefile): make changelog-draft runs scripts/changelog_draft.py with main..HEAD, includes working-tree stats by default, and writes changelog-llm-draft.md. Override with CHANGELOG_HEAD=feature/x CHANGELOG_SINCE=main or CHANGELOG_DRAFT_FLAGS= for commits-only.

Validation

Consequences

Positive

Trade-offs

Related

Page history

Date Change Author
Added Page history section (repository baseline). Ivan Boyarkin