Skip to content

Keep the changelog as scriv fragments - #55

Merged
MattFisher merged 4 commits into
mainfrom
chore/scriv-changelog
Oct 2, 2026
Merged

MattFisher merged 4 commits into
mainfrom
chore/scriv-changelog

Conversation

@MattFisher

@MattFisher MattFisher commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Why

Every PR adds lines under ## [Unreleased] in CHANGELOG.md, so any two open PRs conflict as soon as one merges. That cost a rebase on most of the #29–#54 stack. With fragments, each PR adds its own file under changelog.d/, and nothing conflicts.

What changes

  • uv run scriv create makes a fragment from changelog.d/TEMPLATE.md (Keep a Changelog categories, commented out). Commit it with the change.
  • Releasing: after uv version --bump, run uv run scriv collect. It reads the version from pyproject.toml and writes ## [X.Y.Z] - YYYY-MM-DD, the same heading format as before. compact_fragments = true keeps lists tight when several fragments share a category.
  • The README release steps now go through a release PR and push the tag after it merges. The old steps pushed straight to main, which the protect-main ruleset rejects.
  • CHANGELOG.md: the 30 [Unreleased] entries move unchanged into changelog.d/20261002_000000_unreleased_before_scriv.md, and <!-- scriv-insert-here --> replaces the heading.
  • This comes from Keep scaffolded changelogs as scriv fragments python-project-template#4 via copier update. This repo's pyproject.toml has moved well away from the template: uv_build, the underscore repo URLs, its own extras. So the conflicting hunks keep this repo's side, and the scriv config and dev dependency are added by hand.

Found on the way

  • src/inspect_dataset/__init__.py says __version__ = "0.2.0", but pyproject.toml is at 0.4.0. Runtime code reads the version from package metadata (_version.py), so scan_summary.json is right. Only the exported __version__ is stale. The scriv config reads pyproject.toml for that reason. Not fixed here.
  • The README's uv sync --extra dev (twice) failed with "Extra dev is not defined": dev is a dependency group, installed by default. It is now uv sync.
  • The last released section in CHANGELOG.md is 0.3.4, while pyproject.toml is at 0.4.0. The next scriv collect will write ## [0.4.0] unless the version is bumped first.

Testing

  • pre-commit run --all-files and pytest (636 passed) pass.
  • A rehearsal in a throwaway copy, scriv collect, writes ## [0.4.0] - 2026-10-02 with the moved entries, deletes the fragment, keeps TEMPLATE.md, and passes mdformat.

Follow-up

.copier-answers.yml records template v1.9.1, the release v1 points at, so the weekly template-update run has nothing to propose. Open PR #8 doesn't touch CHANGELOG.md; it needs a new fragment of its own before it merges.

🤖 Generated with Claude Code

Every PR added lines under `## [Unreleased]`, so any two open PRs conflicted
on CHANGELOG.md as soon as one merged. Each PR now adds a fragment under
changelog.d/ (`uv run scriv create`), and `uv run scriv collect` writes them
into CHANGELOG.md at release time.

From python-project-template#4 via `copier update`. This repo's pyproject has
moved well away from the template (uv_build, its own URLs and extras), so the
conflicting hunks keep this repo's side and the scriv config is added by
hand. The version is read from pyproject.toml, which uv_build uses;
__init__.__version__ is stale at 0.2.0. The unreleased entries move unchanged
into one fragment. The README's `uv sync --extra dev` failed, since dev is a
dependency group; it is now `uv sync`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MattFisher

Copy link
Copy Markdown
Collaborator Author

Review of #55

I cloned the PR head (e80be21) into a fresh temp directory and ran uv sync, uv run pre-commit run --all-files (all pass) and uv run pytest -q (636 passed, 15 skipped). The move of [Unreleased] is lossless and the copier resolution is right. Two things will bite at the first release, so they come first.

1. Two or more fragments in one category break mdformat on the release commit

Where: pyproject.toml, [tool.scriv] (lines 47-60).

What is wrong: without compact_fragments, scriv puts a blank line after every fragment it collects. When two fragments add to the same category, the list gets a blank line between them. Markdown then treats the whole list as loose, and mdformat rewrites every item with a blank line between it and the next.

Failure scenario (verified by running): I added two fragments, one with a ### Fixed bullet, and ran uv run scriv collect. The new - A rehearsal fix. landed after a blank line, below the moved Fixed entries. pre-commit run --files CHANGELOG.md then failed: "mdformat ... files were modified by this hook". It added a blank line between each of the ten Fixed bullets. So the release commit fails the hook locally and fails the CI lint job. If you accept mdformat's output, every multi-PR release has spaced-out lists, unlike the tight lists in every earlier section. The rehearsal in the PR description used one fragment, so it could not show this. One fragment per PR makes this the normal case.

Fix: add compact_fragments = true to [tool.scriv]. I checked this. With three fragments (the moved one, one Added with two bullets, one Fixed), collect wrote tight lists, mdformat passed, and markdownlint-cli2 with the repo's .markdownlint.yaml reported 0 issues. Generality-Labs/python-project-template#4 has the same config, so it needs the same line.

2. The README release steps cannot run as written, and the first one picks 0.5.0

Where: README.md lines 215-219.

What is wrong, part (a): git push origin main ... is rejected. The protect-main ruleset on the default branch has a pull_request rule, a required ci / Lint, type-check, and test check, and no bypass actors. These lines are older than this PR, but the PR rewrites the block, so this is a good time to fix it. I checked this by reading the ruleset through the API. I did not try the push.

Part (b), the version (checked by running): the claims in the description hold. __init__.__version__ is "0.2.0", package_version() returns 0.4.0, and the newest changelog section is ## [0.3.4] - 2026-04-04. 0.4.0 was set in pyproject.toml in 0083bb6 but never released. There are no tags and no GitHub releases, and PyPI returns 404 for inspect-dataset. Today, scriv collect writes ## [0.4.0] - 2026-10-02. The README says to run uv version --bump minor first, which gives 0.5.0. Someone who follows the README skips 0.4.0. Someone who follows the PR description ships 0.4.0. Neither label is wrong under semver, but the docs should pick one.

Fix: release through a PR. Create a branch, run uv version --bump ... and uv run scriv collect, and open a PR. After it merges, tag the merge commit on main and push only the tag. For this first release, say whether to skip the bump and ship 0.4.0.

Part (c), a nit: git add -A also stages any stray untracked file in the tree. git commit -am was enough, because the fragments are tracked and -a stages their deletion. uv run scriv collect --add also works.

3. The PR description is wrong about #8

The follow-up says "Open PR #8 edits CHANGELOG.md and will need its entry moved into a fragment." #8 changes PLAN.md, src/ and tests/, but not CHANGELOG.md, so there is nothing to move. It needs a new fragment.

4. Not caused by this PR: the first collected release will leave out features

The moved entries are an exact copy of main's [Unreleased]. But that section was already incomplete. No entry, released or unreleased, adds the markdown_integrity, extraction_artifacts, text_layer_recall or numeric_provenance scanners, the image_mime_type scanner itself, or --scanner-module plugin scanners. I checked this with grep. All of them shipped after 0.3.4. For example, a96ed3f added text_layer_recall and numeric_provenance. The first scriv collect will publish notes without them. A fragment with these entries before the release would fix it.

5. A minor point on the version source

Reading the version from pyproject.toml is right. The template default is literal: src/inspect_dataset/__init__.py: __version__, which is what copier update proposed. With it, collect would write a second ## [0.2.0]. But .github/workflows/release.yml line 9 still says to bump src/inspect_dataset/__init__.py if present. It is present and stale, and nothing in src/ or tests/ reads it. Consider deriving __version__ from package_version() in a follow-up.

What I checked with no problems found

  • Changelog move (run): the fragment matches main's [Unreleased] line for line, apart from the blank lines at each end. That is 30 bullets under Added, Changed and Fixed. The rest of CHANGELOG.md is unchanged apart from the marker.
  • Copier resolution (run): I ran uvx copier update --vcs-ref 399a60e on main. It conflicted only in README.md and pyproject.toml. changelog.d/TEMPLATE.md and .copier-answers.yml are byte-identical to the PR. The one deliberate difference in [tool.scriv] is the version source.
  • scriv create (run): it writes changelog.d/<timestamp>_<user>_<branch>.md, identical to TEMPLATE.md. Commented sections are dropped on collect.
  • Collect with one fragment (run): it writes ## [0.4.0] - 2026-10-02 below the marker, matching the old heading format. It deletes the fragment and keeps TEMPLATE.md. No markdownlint hook is configured, only .markdownlint.yaml. I ran markdownlint-cli2 by hand and it reported 0 issues.
  • The uv sync change (run): uv sync --extra dev fails with "Extra dev is not defined". dev is in [dependency-groups] and there is no default-groups override, so plain uv sync installs it. scriv and pytest import after it.
  • Leftover instructions (read): nothing else tells people to edit [Unreleased]. I searched .claude/, PLAN.md, the README and the workflows.

Posted by Claude Code on Matt's behalf.

- compact_fragments = true, from the template's follow-up commit: two
  fragments in one category no longer leave a blank line that makes the list
  loose and fails mdformat on the release commit.
- The README release steps pushed straight to main, which the protect-main
  ruleset rejects. They now open a release PR and push the tag after it
  merges. git commit -am replaces git add -A, which would stage stray files.

From the review on #55.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MattFisher

Copy link
Copy Markdown
Collaborator Author

Thanks. Actioned in 61fb2a6:

  1. Loose lists. compact_fragments = true, from the template's follow-up (Keep scaffolded changelogs as scriv fragments python-project-template#4). A two-fragment rehearsal now collects into tight lists and passes mdformat.
  2. Release steps. They now go through a release PR and push only the tag after it merges. git commit -am replaces git add -A.
  3. Add gold_fidelity vision scanner (v0.6.2) #8. The PR description is corrected: Add gold_fidelity vision scanner (v0.6.2) #8 needs a new fragment, not a moved entry.

Left for Matt, since they're decisions rather than fixes:

  • Whether the first release ships as 0.4.0 (collect without bumping) or 0.5.0 (following the README).
  • The scanners and --scanner-module that shipped after 0.3.4 with no changelog entry. They need a fragment written by someone who knows them before the first collect.
  • The stale __init__.__version__ (0.2.0) and the release.yml comment that mentions bumping it. A follow-up can derive it from package metadata.

Posted by Claude Code on Matt's behalf.

MattFisher and others added 2 commits October 2, 2026 19:25
The template change this PR adopts is released as v1.9.0. copier update to
the tag changes nothing else.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v1.9.1 repairs the 1.9.0 release tag and changes no scaffolded file. Moving
now saves the weekly template-update run a PR that would only change this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MattFisher
MattFisher merged commit bf358c1 into main Oct 2, 2026
1 check passed
@MattFisher
MattFisher deleted the chore/scriv-changelog branch October 2, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants