feat(changelog): write down what changed, tied to git

Forty-four reader-facing entries and ten release notes, backfilled from
the history and the specs, each naming the commit or range it describes.
Tests pin the shape; a script checks the refs exist, since CI's shallow
checkout can't.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-13 14:23:01 +02:00
1 parent 6b21b88f98
commit 238d21686a
3 files changed
+688

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
/**
* Checks every changelog ref exists in this repository's history, and that a
* note's range runs forwards. Run by hand, or by the agent writing entries:
*
* bun run scripts/check-changelog.ts
*
* Not a test, because CI checks out shallowly and the history is not there.
*/
import { ENTRIES, NOTES } from "../src/shared/changelog.ts";
const exists = (ref: string) =>
Bun.spawnSync(["git", "cat-file", "-e", `${ref}^{commit}`]).exitCode === 0;
const before = (a: string, b: string) =>
Bun.spawnSync(["git", "merge-base", "--is-ancestor", a, b]).exitCode === 0;
const problems: string[] = [];
for (const e of ENTRIES) if (!exists(e.ref)) problems.push(`entry ${e.id}: no commit ${e.ref}`);
for (const n of NOTES) {
for (const ref of [n.from, n.to]) if (!exists(ref)) problems.push(`note ${n.id}: no commit ${ref}`);
if (exists(n.from) && exists(n.to) && !before(n.from, n.to)) {
problems.push(`note ${n.id}: ${n.from} does not come before ${n.to}`);
}
}
if (problems.length > 0) {
console.error(problems.join("\n"));
process.exit(1);
}
console.log(`changelog: ${ENTRIES.length} entries and ${NOTES.length} notes, every ref found.`);