revert: drop the union merge driver for CHANGELOG.md #145

Merged
Grandiras merged 1 commit from revert-changelog-union into main 2026-09-24 18:04:35 +00:00
Owner

Reverts #144. The union merge driver turned out to be harmful.

A line-based union merge doesn't understand the changelog's ### Section structure. When I rebased #114 over main, which had also added subsections to [Unreleased], git aligned the matching ### … header lines and filed #114's Breaking changes bullets under Security. There was no conflict marker, so nothing caught it. Forgejo would squash-merge such a mangled changelog just as silently.

A visible conflict is the safer failure mode. opencode-bot's conflict resolver already handles these (it resolved #143 with a merge commit), and a section-aware local resolver covers rebases.

🤖 Generated with Claude Code

Reverts #144. The union merge driver turned out to be harmful. A line-based union merge doesn't understand the changelog's `### Section` structure. When I rebased #114 over main, which had also added subsections to `[Unreleased]`, git aligned the matching `### …` header lines and filed #114's **Breaking changes** bullets under **Security**. There was no conflict marker, so nothing caught it. Forgejo would squash-merge such a mangled changelog just as silently. A visible conflict is the safer failure mode. opencode-bot's conflict resolver already handles these (it resolved #143 with a merge commit), and a section-aware local resolver covers rebases. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
revert: drop the union merge driver for CHANGELOG.md
All checks were successful
CI / pds-integration (pull_request) Successful in 28s
CI / build-and-test (pull_request) Successful in 59s
Sync Closures to GitHub / sync-closure (pull_request) Successful in 8s
95c9cfadae
Reverts #144. A line-based union merge does not understand the file's
subsections: rebasing a PR over main that had also added subsections to
[Unreleased] silently filed that PR's "Breaking changes" bullets under
"Security", with no conflict to catch it. Forgejo would have squash-merged
such mangled changelogs without complaint. A visible conflict, resolved by
the conflict bot or by a section-aware merge, is the safer failure mode.

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

@claude /review

@claude /review
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/578); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/pr-145/run-578.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

💬 Verdict: comment — notes only, nothing blocking.

Clean, minimal revert of #144: .gitattributes is removed in full, matching exactly what was added, and nothing else references the union merge driver (grepped CHANGELOG.md, docs/, .github/ for other mentions of it — none found). The rationale in the description is concrete and convincing: a line-based union driver aligning ### Breaking changes and ### Security headers during a rebase is a real silent-corruption risk, and "visible conflict beats silent misfile" is a reasonable trade-off given the described resolver tooling (opencode-bot's bot resolver, plus a section-aware local resolver for rebases). No correctness or security issues with the diff itself.

One process note below: neither this PR nor #144 added a CHANGELOG entry, which this repo's own CLAUDE.md treats as a hard requirement for build/CI-surface changes.


⏱ 0m 26s · 6 turns · tokens: 13.0k in / 2.3k out (+196.6k cache-read)
📜 Full session transcript

💬 **Verdict: comment** — notes only, nothing blocking. Clean, minimal revert of #144: `.gitattributes` is removed in full, matching exactly what was added, and nothing else references the union merge driver (grepped `CHANGELOG.md`, `docs/`, `.github/` for other mentions of it — none found). The rationale in the description is concrete and convincing: a line-based union driver aligning `### Breaking changes` and `### Security` headers during a rebase is a real silent-corruption risk, and "visible conflict beats silent misfile" is a reasonable trade-off given the described resolver tooling (opencode-bot's bot resolver, plus a section-aware local resolver for rebases). No correctness or security issues with the diff itself. One process note below: neither this PR nor #144 added a CHANGELOG entry, which this repo's own CLAUDE.md treats as a hard requirement for build/CI-surface changes. --- ⏱ 0m 26s · 6 turns · tokens: 13.0k in / 2.3k out (+196.6k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/pr-145/run-578.md) <!-- claude-verdict:comment --> <!-- claude-reviewed-head:95c9cfadae90a8f739e46e98053607913064d528 -->
@ -1,3 +0,0 @@
# Every PR adds bullets at the top of [Unreleased], so parallel PRs always "conflict" there.
Collaborator

This repo's CLAUDE.md says any commit changing build/CI surface must add a CHANGELOG bullet under [Unreleased], with doc-only/whitespace-only changes as the only stated exceptions — a merge-driver config change doesn't qualify for that exception. This PR doesn't add an entry (and #144, which introduced the driver, didn't either). Consider adding a short ### Changed or ### Removed line explaining the union driver was dropped because it silently misfiled changelog sections across rebases.

This repo's CLAUDE.md says any commit changing build/CI surface must add a CHANGELOG bullet under `[Unreleased]`, with doc-only/whitespace-only changes as the only stated exceptions — a merge-driver config change doesn't qualify for that exception. This PR doesn't add an entry (and #144, which introduced the driver, didn't either). Consider adding a short `### Changed` or `### Removed` line explaining the union driver was dropped because it silently misfiled changelog sections across rebases.
Author
Owner

On the CHANGELOG note: #144 and this PR cancel out exactly. Once this merges, main has no .gitattributes and no merge-behaviour change, as before #144, so there is nothing user-visible to record. A "added then removed" pair in [Unreleased] would only be noise. The entry rule exists so consumers learn about behaviour changes, and this pair has none.

@claude /review

On the CHANGELOG note: #144 and this PR cancel out exactly. Once this merges, `main` has no `.gitattributes` and no merge-behaviour change, as before #144, so there is nothing user-visible to record. A "added then removed" pair in `[Unreleased]` would only be noise. The entry rule exists so consumers learn about behaviour changes, and this pair has none. @claude /review
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/581); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/pr-145/run-581.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

💬 Verdict: comment — notes only, nothing blocking.

No new commits since my last pass — the diff is unchanged (just the full removal of .gitattributes, matching exactly what #144 added). The revert remains clean and the rationale is sound: a line-based union merge driver silently misfiling ### Breaking changes bullets under ### Security during a rebase is a real correctness risk, and a visible conflict is the safer failure mode given the described resolver tooling.

The one note from my last review still stands and remains unaddressed: neither this PR nor #144 added a CHANGELOG entry, which CLAUDE.md treats as a hard requirement for build/CI-surface changes. I raised this as non-blocking last time (verdict was comment, not request_changes), so I'm not blocking on it now either, but flagging again since it wasn't picked up.


⏱ 0m 13s · 5 turns · tokens: 12.5k in / 1.0k out (+165.0k cache-read)
📜 Full session transcript

💬 **Verdict: comment** — notes only, nothing blocking. No new commits since my last pass — the diff is unchanged (just the full removal of `.gitattributes`, matching exactly what #144 added). The revert remains clean and the rationale is sound: a line-based union merge driver silently misfiling `### Breaking changes` bullets under `### Security` during a rebase is a real correctness risk, and a visible conflict is the safer failure mode given the described resolver tooling. The one note from my last review still stands and remains unaddressed: neither this PR nor #144 added a CHANGELOG entry, which CLAUDE.md treats as a hard requirement for build/CI-surface changes. I raised this as non-blocking last time (verdict was `comment`, not `request_changes`), so I'm not blocking on it now either, but flagging again since it wasn't picked up. --- ⏱ 0m 13s · 5 turns · tokens: 12.5k in / 1.0k out (+165.0k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/pr-145/run-581.md) <!-- claude-verdict:comment --> <!-- claude-reviewed-head:95c9cfadae90a8f739e46e98053607913064d528 -->
Collaborator

🔧 Let Claude fix this — tick the box and claude-bot picks up the review above, on this PR branch. Nothing runs until you do.

  • @claude-bot Address the findings of the latest review on this pull request.
🔧 **Let Claude fix this** — tick the box and claude-bot picks up the review above, on this PR branch. Nothing runs until you do. - [ ] @claude-bot Address the findings of the latest review on this pull request. <!-- claude-fix-button:145 -->
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the review runs.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/ATProto.NET/pr-145/run-2026-09-24T18-02-25-314Z.md) — updating every ~5 minutes while the review runs.
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

Clean revert, and the reasoning is sound. The deleted .gitattributes contained only the CHANGELOG.md merge=union line plus comments — no other attributes were defined in it, so nothing else is lost, and since union is a built-in git merge driver no cleanup elsewhere is needed.

The stated harm is real, not hypothetical: the union driver merges without conflict markers, and when a rebase aligns matching ### … header lines as common context it can silently file added bullets under the wrong section. This repo's CHANGELOG is exactly the vulnerable shape (## [Unreleased] with Breaking changes/Changed/Fixed/Removed/Security), and CLAUDE.md requires every commit to add a bullet under [Unreleased], so parallel PRs will always collide there — which is why #144 was added in the first place. A mis-merge is extra costly here because .forgejo/workflows/release.yml extracts release notes verbatim from ## [VERSION] sections by heading, so a mangled merge would flow straight into published release notes. A visible conflict is the safer failure mode.

Verified nothing in the repo (CONTRIBUTING.md, CLAUDE.md, .github/skills/issue-workflow/SKILL.md, workflows, docs) references merge=union or .gitattributes, so no stale documentation remains.

Minor note, non-blocking: nothing records the new expectation that CHANGELOG conflicts are now resolved by hand (section-aware) rather than auto-unioned — a one-line mention in CONTRIBUTING.md or CLAUDE.md could spare a future contributor the confusion, but that can happen whenever it's convenient.


⏱ 1m 5s · 6 steps · $0.0078 · tokens: 34.4k in / 3.3k out (+29.2k cache-read) · Go: 5h 0% · wk 95% · mo 80%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Clean revert, and the reasoning is sound. The deleted `.gitattributes` contained only the `CHANGELOG.md merge=union` line plus comments — no other attributes were defined in it, so nothing else is lost, and since `union` is a built-in git merge driver no cleanup elsewhere is needed. The stated harm is real, not hypothetical: the union driver merges without conflict markers, and when a rebase aligns matching `### …` header lines as common context it can silently file added bullets under the wrong section. This repo's CHANGELOG is exactly the vulnerable shape (`## [Unreleased]` with `Breaking changes`/`Changed`/`Fixed`/`Removed`/`Security`), and CLAUDE.md requires every commit to add a bullet under `[Unreleased]`, so parallel PRs will always collide there — which is why #144 was added in the first place. A mis-merge is extra costly here because `.forgejo/workflows/release.yml` extracts release notes verbatim from `## [VERSION]` sections by heading, so a mangled merge would flow straight into published release notes. A visible conflict is the safer failure mode. Verified nothing in the repo (CONTRIBUTING.md, CLAUDE.md, `.github/skills/issue-workflow/SKILL.md`, workflows, docs) references `merge=union` or `.gitattributes`, so no stale documentation remains. Minor note, non-blocking: nothing records the new expectation that CHANGELOG conflicts are now resolved by hand (section-aware) rather than auto-unioned — a one-line mention in CONTRIBUTING.md or CLAUDE.md could spare a future contributor the confusion, but that can happen whenever it's convenient. --- ⏱ 1m 5s · 6 steps · $0.0078 · tokens: 34.4k in / 3.3k out (+29.2k cache-read) · Go: 5h 0% · wk 95% · mo 80% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/ATProto.NET/pr-145/run-2026-09-24T18-02-25-314Z.md) <!-- opencode-reviewed-head:95c9cfadae90a8f739e46e98053607913064d528 --> <!-- opencode-verdict:approve -->
Grandiras deleted branch revert-changelog-union 2026-09-24 18:04:35 +00:00
Sign in to join this conversation.
No description provided.