by Changelog AI (LX AI)

Last updated: 2026-09-16

Dev vs customer tone presets for the same commits

Developers want detail; customers want benefits. Tone presets draft both; SemVer meaning remains your contract.

Why separate tone presets?

I started this project because I saw teams waste time rewriting the same changelog entry for two different readers. Engineers need to see what changed in the code, which files were touched, and any breaking internal APIs. Product managers, support staff, and end users care about what the change means for them: new features, fixed bugs, improved performance, or removed limits. A single tone cannot serve both groups well. By creating two distinct presets that operate on the same commit list, we keep the source of truth unchanged while delivering tailored messages. This approach also lets the SemVer label stay the single source of contractual meaning, because the label is attached to the commit group, not to the wording.

Developer tone preset: detail‑first

Commit‑level detail

When the developer preset is active, the AI expands each commit into a sentence that includes the file path, the function or class modified, and the nature of the change (addition, deletion, refactor). For example, a commit that fixes a null‑pointer in src/api/user.go becomes: “Fixed nil pointer dereference in GetUserByID when the incoming ID is zero, added guard clause and unit test.”

Linking to tracking systems

If the commit message contains an issue ID (e.g., ABC-123), the preset wraps it in a link to the tracker, assuming the team has configured the base URL. This lets engineers jump straight to the discussion or design doc without leaving the changelog.

Including technical context

The preset adds any relevant compiler warnings, test coverage changes, or performance benchmark deltas that appeared in the CI run associated with the commit. This gives a quick health check for the modified area.

Safety and compliance checks for LLM output

Because the text is generated by a language model, I run it through a lightweight safety filter that checks for disallowed content. The filter references the OWASP LLM Top 10 for prompt injection risks and the NIST AI Risk Management Framework for guidance on managing hallucinations and bias. If a segment triggers a rule, it is flagged for human review before publishing.

Example list for a typical release

Customer tone preset: benefit‑first

Outcome‑focused language

With the customer preset, the AI rewrites each commit into a sentence that describes what the user can now do or what problem is solved. Technical jargon is replaced with plain terms. The same null‑pointer fix becomes: “Users will no longer see an error when entering a zero‑value ID in the user lookup field.”

Avoiding internal identifiers

Commit hashes, branch names, and internal issue numbers are omitted unless they are part of a public feature flag or a versioned API endpoint that customers might reference. The goal is to keep the noise low.

Highlighting user impact

If a commit improves performance, the preset translates the benchmark gain into a user‑visible statement: “Page load times are now up to 15% faster on mobile devices.” If a commit removes a limit, it reads: “You can now upload files up to 100 MB instead of the previous 25 MB cap.”

Linking to public documentation

When a change touches a public API endpoint or a configuration option, the preset adds a link to the relevant documentation section, assuming the docs site follows a predictable URL pattern (e.g., https://docs.example.com/api/v2/users).

Example list for the same release

From commit diff to two narratives

Parsing and grouping

The pipeline begins by running git log --pretty=format:%H %s %b --since="1 week ago" to collect commits since the last tag. Each commit is parsed for its conventional‑commit type (feat, fix, perf, refactor, etc.) and scope. Commits with the same type and SemVer implication are grouped together because they will share the same version bump.

Applying tone‑specific prompts

For each group I build two prompts: one tuned for the developer preset, one for the customer preset. The developer prompt asks for “a detailed, technical description that includes file names, symbols, and any relevant test or benchmark changes.” The customer prompt asks for “a concise, benefit‑oriented explanation that avoids internal jargon and focuses on what the user experiences.” The same list of commits feeds both prompts, ensuring the underlying facts stay identical.

Human‑in‑the‑loop review

The AI output lands in a draft editor where a maintainer can accept, edit, or reject each sentence. I have found that most edits are minor wording tweaks rather than factual changes, which shows the model is good at staying true to the source diff. After review, the draft is rendered into Markdown and then HTML for publishing.

Table: mapping conventional commit types to tone phrasing

Commit type Developer phrasing example Customer phrasing example
feat Added ExportCSV method to ReportService that streams rows to reduce memory usage. You can now download reports as CSV files directly from the export button.
fix Resolved deadlock in JobQueue.Push when a nil job was enqueued under high load. Jobs will no longer get stuck when the system is busy.
perf Replaced O(n²) lookup in TagIndex.Find with a hash map, cutting latency from 12 ms to 0.8 ms for 10 k tags. Tag searches are now noticeably faster, especially with large libraries.
refactor Extracted PasswordValidator interface from AuthHandler to allow pluggable strength rules. Password requirements can now be adjusted without changing core login code.
docs Updated API.md with new PATCH /users/:id endpoint description and sample payload. The help center now shows how to partially update a user profile.

Preserving SemVer meaning across tones

Version bump rules stay anchored to commits

The SemVer label is determined solely by the conventional‑commit types in the group: a feat triggers a minor bump, a fix a patch, and a breaking change a major bump. Because the tone presets do not alter the commit messages or their types, the resulting version number is identical whether you read the developer or the customer version.

Contract consistency

I treat the SemVer tag as the contract between the producer and the consumer of the software. The changelog is merely a human‑readable expression of that contract. By keeping the contract untouched, teams can rely on automated tools (like release bots or dependency checkers) to interpret the version correctly, while the dual‑tone changelog serves the two audiences without creating ambiguity.

Example of a major release

Suppose a commit adds BREAKING CHANGE: remove legacy v1 API. The developer preset will note the exact file deletions and the migration steps required. The customer preset will explain that the old API endpoint is no longer available and point users to the v2 documentation. In both cases the version moves from 2.4.1 to 3.0.0, preserving the contractual meaning.

What this is NOT

I want to be clear about the limits of this approach so you can set realistic expectations.

References