(changelog): keep a user-facing changelog, and show What's new after an update - #365
Merged
Merged
Conversation
…an update Nothing told a user what changed when the app updated: the GitHub release notes were the commit subjects, written about the code, and nobody opens them after an automatic update. - CHANGELOG.md at the root: an Unreleased section, then one section per version with New / Changed / Fixed entries on what the user sees. Backfilled for v0.0.80 to v0.0.84 and filled with what main carries since v0.0.84. - docs/changelog.md holds the writing rule; the finish-work list in .ai/shared-guidelines.md asks every behaviour change for its entry. - The release bump dates the Unreleased section, and the publish job writes the release body from that section (scripts/changelog-section.js) instead of the commit subjects, still failing on an empty body. - A changelog job in test.yml fails a PR that changes shipped app code without touching CHANGELOG.md, unless it has the no-changelog label. - A What's new dialog: on the first start after an update it lists every section after the stored lastSeenVersion up to the running version, skipped versions included, and records the version when closed. A fresh install records the version and shows nothing; a missing or unparsable file shows nothing and logs a warning. Help -> What's new reopens the running version's section. CHANGELOG.md is packaged and read main-side. Closes #363
…e CI check end to end - An install updated from v0.0.84 has no lastSeenVersion, so it took the fresh-install path and never saw the dialog. main.js now records, as it loads, whether the database already held a global settings row or the initial-scan marker; such an install without the key is treated as having seen 0.0.84, the last release without the dialog. - The startup, dismissal and menu logic moves into createWhatsNew() in changelog.js, so dismissing is tested against a settings store: the version persists, other global keys survive, and the next start shows nothing. Deleting the write no longer leaves the suite green. - scripts/check-changelog.js takes the PR's base and head SHAs and diffs them through their merge base, so every commit of the PR counts and changes from main do not. It reads the labels through gh itself; the workflow only invokes it. Tested end to end on a temporary repository and a fake gh. - The build workflow's checkout comment says what full history is still for: finding the previous tag.
Brings in #355, whose entry goes under Unreleased next.
What a user sees of #355: a save no longer overwrites a file that changed on disk, an external change is reloaded or reported, file tabs keep their unsaved edits across tab and session switches, and undo stays within the file on screen. Its Windows work-file index fix has no entry: the index signature carries each file's mtime and size, so a save was reindexed on the next listing anyway.
…dd two #355 entries - The CHANGELOG check diffs with --no-renames: with rename detection, moving public/foo.js to docs/foo.js listed only docs/foo.js, and the PR passed without an entry. - The e2e tests create their repositories with git init and symbolic-ref instead of git init -b, which git 2.24 does not know. - Unreleased gains two #355 fixes users see: a failed save now says so, and an answered MCP diff's Save is disabled.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #363
What changes
CHANGELOG.mdat the root:## Unreleased, then## vX.Y.Z — YYYY-MM-DDsections, newest first, each with### New/### Changed/### Fixed. An entry says in one or two sentences what the user sees, with its ref at the end. A---line closes the last section, and the pointer to GitHub Releases for older versions sits under it.## Unreleased: (header): give the session header's controls one order and one look #348, (changes): show an untracked file's line counts without opening it #350, (changes): bring the Changes panel and its editor onto the app's look and feel #351, (terminal): define the plain terminal's claude shim without typing it into the shell #352, (sidebar): keep the subagents of an archived parent out of the orphan group #354, and this PR. (docs): rewrite the README and docs/ against the code, one page per area #357 is docs-only, so it has no entry.The rule, where it is read:
docs/changelog.mdcovers the file, how to write an entry, the CI check and the dialog. It is linked fromdocs/releasing.md,docs/README.mdandCHANGELOG.mditself..ai/shared-guidelines.mdcarries one new "When you finish work" step and one orientation row.Release procedure (
docs/releasing.md,.claude/commands/release.md): the bump PR renames## Unreleasedto the version and its date, and opens a new empty one. The publish job's "Fill in release notes" step now writes the body from that section (scripts/changelog-section.js <tag>), followed by the same Full changelog compare link as before. It still fails rather than publish an empty body, now when the section is missing or empty. The commit-subject list is gone. Step 9 of the command no longer prepends a summary: the notes and the app's dialog must say the same thing, so wording is changed inCHANGELOG.md.test/changelog.test.jsfails whenpackage.json's version has no section, so a bump without one does not pass CI.CI check: a
changelogjob intest.yml, on pull requests only.HEAD^1..HEADof the merge commit) touches app code but notCHANGELOG.md.*.jsfiles excepteslint.config.js,public/,workers/andscripts/claude-sandbox.sh.no-changeloglabel (created) waives it. The labels are read through the API at run time, so after adding the label a re-run of the failed job passes.labeledevents do not re-run the whole test matrix.scripts/check-changelog.js.What's new dialog:
changelog.js,main.js):whats-new-startupcomparesapp.getVersion()withglobal.lastSeenVersion, whose defaultnullis inSETTING_DEFAULTS.(lastSeen, current], newest first, skipped versions included.whats-new-dismissedrecords the running version when it closes.[whats-new]warning in the main log, no dialog, nothing recorded.CHANGELOG.mdis added tobuild.filesand read from__dirname, which isapp.asarin a packaged build.window-frame.js). It sendsshow-whats-newwith the running version's section.public/whats-new.js):###,-bullets, paragraphs, bold, inline code, links.escapeHtml. Only an http(s) URL with no quote or angle bracket becomes a link, and a click on it goes toopenExternal..whats-new-overlayis in the window strip's no-drag list.Evidence
Tests written first, each seen red on its assertions against a stub, then green:
test/changelog.test.jstest/whats-new.test.jstest/check-changelog.test.jstest/changelog-section.test.jstest/whats-new-wiring.test.jstest/window-frame.test.jsMutations: each guard was mutated alone and the suite rerun. All 66 are caught.
The first pass had four survivors:
parseChangelog:splitthrows anyway, so the guard is removed.Live (Playwright, throwaway HOME, one data directory across three launches of this branch):
lastSeenVersion= 0.0.84.lastSeenVersionseeded to 0.0.81, then relaunched:overflow-y: auto, scrollHeight 665 > 663) and the dialog stays under 80 vh.prefers-color-scheme: lightemulated, the dialog keeps its colours.15/15 checks passed.
Gate:
eslint .has 0 errors, and its 343 warnings are all pre-existing. The full suite runs through the pre-commit hook.