From 2d5052e37a2ed7b308b83e5c76b88ef1eb88aa2d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 13:30:39 +0000 Subject: [PATCH 1/2] todo: split the changelog migration into three issues Replace the single three-stage plan with three todo files: replacing CHANGELOG.md with a changelog/ directory (P1, the merge-conflict fix), publishing the structure on the website (P4, blocked by the first), and an investigation into generating the changelog from Git history (P4). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_013RUcrfUKZ3tbjGqkF5xncc --- todo/changelog-directory.md | 59 ++++++++++++++++++++++++++++++ todo/changelog-from-git-history.md | 48 ++++++++++++++++++++++++ todo/changelog-website.md | 33 +++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 todo/changelog-directory.md create mode 100644 todo/changelog-from-git-history.md create mode 100644 todo/changelog-website.md diff --git a/todo/changelog-directory.md b/todo/changelog-directory.md new file mode 100644 index 000000000..983a7de7a --- /dev/null +++ b/todo/changelog-directory.md @@ -0,0 +1,59 @@ +# Replace `CHANGELOG.md` with a `changelog/` directory + +**Priority:** P1 +**Status:** open + +## Problem + +Every PR adds its entry at the top of `## Unreleased` in `CHANGELOG.md`, so any +two concurrent PRs conflict on the same lines. The file is also over 2000 lines +and keeps growing. + +## Proposal + +Replace the single file with a directory: + +``` +changelog/ + README.md <- the current CHANGELOG preamble: versioning convention, + entry-style rules + unreleased/ + .md <- one file per changelog-worthy PR, named by PR number + .md <- retrofitted released sections, one file per release +``` + +- A PR adds `changelog/unreleased/.md` instead of editing a shared file — + PR numbers are unique, so concurrent PRs can never conflict. A PR with + several entries puts them all in its one file. The `**BREAKING CHANGES:**` + marker keeps its meaning; at release time it is found by scanning + `changelog/unreleased/`. +- Entry ordering: PR numbers are monotonic, so sorting filenames by number + descending reproduces the current newest-first order. +- Releasing: concatenate `unreleased/*.md` (descending) into + `changelog/.md` and delete the entry files. Git does not store + empty directories, so `unreleased/` needs a permanent file (`.gitkeep` or a + one-line `README.md`). +- Retrofit: released sections move as one file per version + (`changelog/0.44.0.md`, …). Splitting history per PR would be churn with no + benefit — conflicts only ever happen in `unreleased` — and pre-convention + entries have no PR number to name a file by. +- Entries stay in the Markdown subset they already use (paragraphs, list + items, inline code, bold, PR links). Publishing the changelog on the website + ([changelog-website.md](./changelog-website.md)) needs to render entries with + a small self-hosted parser, so the subset is the convention, not an accident. + +## Tasks + +- [ ] Create `changelog/README.md` from the `CHANGELOG.md` preamble +- [ ] Retrofit released sections as `changelog/.md` +- [ ] Create `changelog/unreleased/` with its permanent file and move any + unreleased entries into per-PR files +- [ ] Delete `CHANGELOG.md`, or leave a short stub pointing at `changelog/` +- [ ] Update `AGENTS.md` §8.3 (entry workflow) and §8.4 (release step) and + `CONTRIBUTING.md` to describe the directory + +## Related + +- [changelog-website.md](./changelog-website.md) — consumes this structure +- [changelog-from-git-history.md](./changelog-from-git-history.md) — may + eventually replace this structure diff --git a/todo/changelog-from-git-history.md b/todo/changelog-from-git-history.md new file mode 100644 index 000000000..9e8709848 --- /dev/null +++ b/todo/changelog-from-git-history.md @@ -0,0 +1,48 @@ +# Investigate generating the changelog from Git history + +**Priority:** P4 +**Status:** open + +## Problem + +Even as per-PR files ([changelog-directory.md](./changelog-directory.md)), +changelog entries are authored by hand while the same information — commits, +diffs, PR links — already exists in Git history. It may be possible to remove +the `changelog/` directory and derive the release history directly: + +``` +Git history -> changelog generator -> FunctionalScript website +``` + +This is an investigation, not a commitment: summarizing diffs at build time +would make the published notes non-deterministic and unreviewed, and Git +history is immutable, so a badly worded source could never be fixed — while a +committed entry can be fixed by a cleanup PR. The `**BREAKING CHANGES:**` +marker also drives version bumps, and that signal must stay reviewed. + +## Proposal + +Evaluate at least these designs before removing `changelog/`: + +1. **Commit-message extraction.** The entry lives in the squash/merge commit + message (e.g. a `Changelog:` trailer, reviewed as part of the PR). The + generator deterministically extracts trailers between release tags — no + summarization, reviewed text, `changelog/` genuinely redundant. +2. **Authoring assistant.** A tool drafts the entry from the PR's diff at PR + time; the reviewed result is still committed as a `changelog/` file. The + generator stays out of the build; `changelog/` remains the source of truth. +3. **Build-time summarization.** The generator reads commits and diffs and + writes the prose itself. Only acceptable if the output is deterministic and + there is a reviewed override mechanism — which tends to reinvent + `changelog/`. + +Decide on criteria: determinism of the published pages, where review happens, +how a published mistake gets fixed, and where the breaking-change signal for +versioning comes from. + +## Related + +- [changelog-directory.md](./changelog-directory.md) — the structure this + would replace +- [changelog-website.md](./changelog-website.md) — the consumer that must not + care which source feeds it diff --git a/todo/changelog-website.md b/todo/changelog-website.md new file mode 100644 index 000000000..0c68ece1d --- /dev/null +++ b/todo/changelog-website.md @@ -0,0 +1,33 @@ +# Publish the changelog on the website + +**Priority:** P4 +**Status:** blocked +**Blocked by:** [Replace `CHANGELOG.md` with a `changelog/` directory](./changelog-directory.md) + +## Problem + +The release history lives only in the repository. Users of the package should +be able to read it on the FunctionalScript website as an index of releases and +a page per release. + +## Proposal + +Extend the website generator (`fjs/website`) to read the `changelog/` +directory and emit an index page plus one page per release. The repository +remains the source of truth; the website is presentation. + +The main cost is rendering: the repo has no Markdown parser. Either write a +small self-hosted parser for the entry subset (paragraphs, list items, inline +code, bold, links — all the current entries use), or reconsider the entry +format. The BNF machinery is a natural fit for the parser. + +## Tasks + +- [ ] Parser for the changelog Markdown subset +- [ ] Release index page and per-release pages in `fjs/website` +- [ ] Link the changelog from the landing page + +## Related + +- [changelog-directory.md](./changelog-directory.md) — defines the structure + and the Markdown subset this consumes From ddb2cb7a1e08fc579f36221607d101df30abe128 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 14:31:59 +0000 Subject: [PATCH 2/2] todo/changelog-directory: PR-number order is the order, not merge order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review on #1551 showed the ordering claim was wrong: the current CHANGELOG is in merge order, which a descending PR-number sort does not reproduce. State the deviation as accepted — deterministic and conflict-free now, with exact merge order recoverable later by generating from Git history. Also lower the priority to P2: nothing is blocked on this, which is what P1 means in todo/README.md. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_013RUcrfUKZ3tbjGqkF5xncc --- todo/changelog-directory.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/todo/changelog-directory.md b/todo/changelog-directory.md index 983a7de7a..cb59b4360 100644 --- a/todo/changelog-directory.md +++ b/todo/changelog-directory.md @@ -1,6 +1,6 @@ # Replace `CHANGELOG.md` with a `changelog/` directory -**Priority:** P1 +**Priority:** P2 **Status:** open ## Problem @@ -27,8 +27,12 @@ changelog/ several entries puts them all in its one file. The `**BREAKING CHANGES:**` marker keeps its meaning; at release time it is found by scanning `changelog/unreleased/`. -- Entry ordering: PR numbers are monotonic, so sorting filenames by number - descending reproduces the current newest-first order. +- Entry ordering: filenames sort by PR number descending. Today's file is in + *merge* order, which this does not reproduce exactly — a PR opened earlier + can merge after one opened later. That deviation is accepted: PR-number + order is deterministic and conflict-free, and exact merge order can be + recovered later by generating from Git history + ([changelog-from-git-history.md](./changelog-from-git-history.md)). - Releasing: concatenate `unreleased/*.md` (descending) into `changelog/.md` and delete the entry files. Git does not store empty directories, so `unreleased/` needs a permanent file (`.gitkeep` or a