SemVer Derivation Rules¶
To avoid the pitfalls of using Keep a Changelog categories directly for SemVer (where a simple change would trigger a false-positive Major bump), ChangeSharp uses a refined, pragmatic mapping:
| Fragment Section | SemVer Impact | Description / Discipline |
|---|---|---|
### Breaking Changes |
⬆️ Major | Explicit breaking changes. Kept as a separate section in the fragment and compiled into the final release notes for clear visibility. |
### Removed |
⬆️ Major | Removing a documented public feature is a breaking change. |
### Changed |
➡️ Minor | Modifications to existing features. Note: By default, ChangeSharp treats "Changed" as a Minor bump to avoid accidental Major bumps. Override to "Major" in changesharp.json if needed. |
### Added |
➡️ Minor | New backward-compatible features. |
### Deprecated |
➡️ Minor | Warnings about future removals. |
### Fixed |
🛞 Patch | Bug fixes. |
### Security |
🛞 Patch | Security improvements. |
Customization¶
You can override these default mappings or define entirely new categories in your changesharp.json configuration file. This is useful for internal maintenance, documentation changes, or specific project workflows.
{
"SemverPolicy": {
"Mappings": {
"Breaking Changes": "Major",
"Added": "Minor",
"Maintenance": "Patch",
"Documentation": "None"
}
}
}
Impact levels supported: Major, Minor, Patch, None.
🛡️ Automated Verification (Safety Gates)¶
Human error is the main cause of SemVer violations. ChangeSharp provides a Safety Gate via the --api-min-level flag to cross-verify fragments against actual code changes.
How it works¶
The CI pipeline runs an API diff tool of its choice (e.g., PublicApiAnalyzers, Swagger diff) and passes the minimum impact level to ChangeSharp:
changesharp validate --api-min-level minor # PR gate
changesharp release --api-min-level major # release gate
ChangeSharp compares the required level against the fragments' declared categories:
1. Extract Expected Impact: ChangeSharp reads the pending fragments (e.g., ### Added implies Minor).
2. Compare: If the fragments' highest impact is below --api-min-level, validation fails.
3. Fail or Warn: Use --api-min-level-warn to warn instead of failing.
Integration Examples¶
- Web APIs: Compare Swagger/OpenAPI schemas before
changesharp validate --api-min-level. - .NET Libraries: Use
PublicApiGeneratorto detect signature changes. - CLI Tools: Compare help output or command schemas.
ChangeSharp does not perform the API diff itself — it only enforces the policy. See ApiSurfaceGate for details.
⛔ Maximum Impact Cap (SemverPolicy.MaxImpact)¶
--api-min-level is a floor: it guarantees fragments are not lower than the real API impact. SemverPolicy.MaxImpact is the symmetric cap: it guarantees no fragment silently forces a Major bump when the team does not want one.
{
"SemverPolicy": {
"MaxImpact": "minor"
}
}
MaxImpact accepts patch, minor, or major. The default is major, which disables the cap entirely — existing projects are unaffected until they opt in.
Note on custom mappings: the cap applies to the impact level your
Mappingsdeclare, not to whether a change is actually breaking. If you mapChanged → Major(like this repository does) and setMaxImpact: minor, thenchangesharp new --changedis blocked too — even for harmless changes. With such a mapping, chooseMaxImpact: major(or accept that everyChangedneeds--allow-major).
Where it is enforced¶
| Step | Behavior |
|---|---|
changesharp new (flags) |
Category above the cap → refused (exit 3) unless --allow-major |
changesharp new (interactive) |
Blocked categories are marked ⚠ blocked (MaxImpact) in the menu and re-prompted |
changesharp validate |
Does not enforce the cap (format check only) |
changesharp release |
Refused (exit 3) unless --allow-major — the production gate (human-in-the-loop) |
changesharp new --breaking # ❌ refused above the cap
changesharp new --breaking --allow-major # ✅ deliberate
changesharp release # ❌ refused above the cap
changesharp release --allow-major # ✅ deliberate
The --allow-major flag is the explicit opt-in at both creation and release, so a Major requires two deliberate decisions. A runnable demo lives in samples/maximpact-gate/.
Known limits¶
The gates are enforced per command: the --api-min-level floor on validate and release, the MaxImpact cap on new and release. The prerelease create/promote path bypasses them: changesharp prerelease --promote promotes a pre-release to a final release without any gate check. This matches the pre-existing behavior of --api-min-level on that path; if you rely on the gates, run changesharp validate --api-min-level <level> (or changesharp release --allow-major) as an explicit check before promoting.