Product Changelog vs. Main Branch Activity
LenserFight publishes two deliberately different pages, and conflating them is exactly the failure mode this page exists to prevent:
| Product Changelog | Main Branch Activity | |
|---|---|---|
| Audience | End users deciding whether to upgrade | Contributors, integrators, auditors |
| Authored by | A maintainer, by hand | Generated on every build |
| Source | .changes/<pr-number>.md fragments, aggregated into dated version sections | Full git history (main, first-parent) + GitHub PR metadata |
| Contains | What shipped: additions, fixes, security, deprecations, breaking changes, migration notes | Every PR/commit merged to main, whether or not it has shipped |
| Updated | Only when a maintainer runs pnpm changelog:cut | Every apps/docs build |
A merged change is not a released change
Being merged to main means the change passed review and CI. It does not mean it has shipped to users, and it can still be reverted before anything ships. The Main Branch Activity ledger says this explicitly in its banner and labels every entry Unreleased, Released, or Internal — never inferred from the commit message, only from whether the commit is reachable from a published release tag.
Where the data comes from — and where it deliberately doesn't
We do not generate public prose from arbitrary commit messages. A commit subject tells you what a contributor typed, not what a user should be told, and it does not carry category, user impact, or verification evidence in a structured way. Instead:
- Every user-facing pull request adds a
.changes/<pr-number>.mdfragment (schema:.changes/schema.json). This is the only source of prose for both pages. .github/workflows/changelog-gate.ymlblocks a PR that has neither a valid fragment nor an approvedchangelog:nonelabel + reason.- Fields with no fragment/PR-metadata evidence render
Not declaredorVerification unavailable— never a guess.
Generation, not commit-back
tools/changelog/cli.mjs runs as a step in the docs project's Nx build/serve targets (apps/docs/project.json), writing JSON under docs/public/changelog-data/ (gitignored — never committed). Whatever platform builds apps/docs on every push to main regenerates this data as part of that same build; nothing is written back to git, so there's no bot-commit loop to guard against. See tools/changelog/ for the generation logic and its test suite.
Cutting a release — stamping the aggregated Unreleased fragments into a dated version section of the Product Changelog — is a manual step (pnpm changelog:cut <version>), run by a maintainer, then reviewed and merged like any other change. This is what "human-curated" means in practice: the platform never decides on its own that something is released.
Package changelogs stay separate
apps/cli/CHANGELOG.md, libs/sdk/CHANGELOG.md, and libs/adapters/connector/CHANGELOG.md are generated by Nx Release from conventional commits, exactly as before — this system doesn't replace or duplicate that. Product Changelog entries link to the relevant package changelog when a change is tied to a package release.
Legacy history
The old standard-version-generated CHANGELOG.md (85,000+ lines, with duplicated entries and unfiltered internal commits mixed into user-facing ones) was retired as the public-facing changelog because it had stopped being usable by the people it was meant to inform. It isn't in the working tree, but it's still recoverable from git history — see the root CHANGELOG.md for exactly how.